RenderScript is a framework for running computationally intensive tasks at high performance on Android. It is designed for use with data-parallel computation, although serial workloads can benefit as well. The RenderScript runtime parallelizes work across processors available on a device, such as multi-core CPUs and GPUs, enabling developers to focus on expressing algorithms rather than scheduling work. RenderScript is especially useful for apps performing image processing, computational photography, or computer vision.
Devices running Android 8.0 and higher use the following RenderScript framework and vendor HALs:
Figure 1. Vendor code linking to internal libs.
Differences from RenderScript in Android 7.x and lower include:
- Two instances of RenderScript internal libs in a process. One set is for
CPU fallback path and is from directly at
/system/lib
; the other set is for GPU path and is from/system/lib/vndk-sp
. - RS internal libs in
/system/lib
are built as part of the platform and are updated assystem.img
is upgraded. However, libs in/system/lib/vndk-sp
are built for the vendor and are not updated whensystem.img
is upgraded (while they can be updated for a security fix, their ABI remains the same). - Vendor code (RS HAL, RS driver, and the
bcc plugin
) are linked against the RenderScript internal libs located at/system/lib/vndk-sp
. They cannot link against libs in/system/lib
because libs in that directory are built for the platform and thus may not be compatible with the vendor code (i.e., symbols may be removed). Doing so would make a framework-only OTA impossible.
Design
The following sections detail RenderScript design in Android 8.0 and higher.
RenderScript libs available to vendors
This section lists the RenderScript libs (known as Vendor NDK for Same-Process HALs or VNDK-SP) that are available to vendor code and which can be linked against. It also details additional libraries that are unrelated to RenderScript but which are also provided to vendor code.
While the following list of libraries might differ between Android releases,
it is immutable for a specific Android release; for an up-to-date list of
available libraries, refer to /system/etc/ld.config.txt
.
RenderScript Libs | Non-RenderScript Libs |
---|---|
|
|
Linker namespace configuration
The linking restriction that prevents libs not in VNDK-SP from being used by vendor code is enforced at runtime using the linker namespace. (For details, refer to the VNDK Design presentation.)
On a device running Android 8.0 and higher, all Same-Process HALs (SP-HALs)
except RenderScript are loaded inside the linker namespace
sphal
. RenderScript is loaded into the RenderScript-specific
namespace rs
, a location that enables a slightly looser
enforcement for RenderScript libs. Because the RS implementation needs to load
the compiled bitcode, /data/*/*.so
is added to the path of the
rs
namespace (other SP-HALs are not allowed to load libs from the
data partition).
In addition, the rs
namespace allows more libs than provided for
by other namespaces. libmediandk.so
and libft2.so
are exposed to the rs
namespace because
libRS_internal.so
has an internal dependency to these libraries.
Figure 2. Namespace configuration for linker.
Load drivers
CPU fallback path
Depending on the existence of the RS_CONTEXT_LOW_LATENCY
bit
when creating an RS context, either the CPU or GPU path is selected. When the
CPU path is selected, libRS_internal.so
(the main implementation
of the RS framework) is directly dlopen
ed from the default linker
namespace where the platform version of RS libs are provided.
The RS HAL implementation from the vendor is not used at all when the CPU
fallback path is taken, and an RsContext
object is created with
null mVendorDriverName
. libRSDriver.so
is (by
default) dlopen
ed and the driver lib is loaded from the
default
namespace because the caller
(libRS_internal.so
) is also loaded in the default
namespace.
Figure 3. CPU fallback path.
GPU path
For the GPU path, the libRS_internal.so
is loaded differently.
First, libRS.so
uses
android.hardware.renderscript@1.0.so
(and its underlying
libhidltransport.so
) to load
android.hardware.renderscript@1.0-impl.so
(a vendor
implementation of RS HAL) into a different linker namespace called
sphal
. The RS
HAL then dlopen
s libRS_internal.so
in a another
linker namespace called rs
.
Vendors can provide their own RS driver by setting the build time flag
OVERRIDE_RS_DRIVER
, which is embedded into the RS HAL
implementation
(hardware/interfaces/renderscript/1.0/default/Context.cpp
). This
driver name is then dlopen
ed for the RS context for the GPU path.
The creation of the RsContext
object is delegated to the RS HAL
implementation. The HAL calls back to the RS framework using
rsContextCreateVendor()
function with the name of the driver to
use as an argument. The RS framework then loads the specified driver when the
RsContext
is initialized. In this case, the driver library is
loaded into the rs
namespace because the RsContext
object is created inside the rs
namespace and
/vendor/lib
is in the search path of the namespace.
Figure 4. GPU fallback path.
When transitioning from the default
namespace to the
sphal
namespace, libhidltransport.so
uses the
android_load_sphal_library()
function to explicitly order the
dynamic linker to load the -impl.so
library from the
sphal
namespace.
When transitioning from the sphal
namespace to the
rs
namespace, loading is done indirectly by the following line in
/system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
This line specifies the dynamic linker should load
libRS_internal.so
from the rs
namespace when the lib
can't be found/loaded from the sphal
namespace (which is always
the case because sphal
namespace does not search
/system/lib/vndk-sp
where libRS_internal.so
resides). With this configuration, a simple dlopen()
call to
libRS_internal.so
is enough to make the namespace transition.
Load bcc plugin
bcc plugin
is a vendor-provided library loaded into the
bcc
compiler. Because bcc
is a system process in the
/system/bin
directory, the bcc plugin
library can be
considered an SP-HAL (i.e., a vendor HAL that can be directly loaded into the
system process without being binderized). As an SP-HAL, the
bcc-plugin
library:
- Cannot link against framework-only libraries such as
libLLVM.so
. - Can link against only the VNDK-SP libraries available to the vendor.
This restriction is enforced by loading the bcc plugin
into the
sphal
namespace using the
android_sphal_load_library()
function. In previous versions of
Android, the plugin name was specified using the -load
option and
the lib was loaded using the simple dlopen()
by
libLLVM.so
. In Android 8.0 and higher, this is specified in the
-plugin
option and the lib is directly loaded by the
bcc
itself. This option enables a non-Android-specific path to
the open source LLVM project.
Figure 5. Loading bcc plugin, Android 7.x and lower.
Figure 6. Loading bcc plugin, Android 8.0 and higher.
Search paths for ld.mc
When executing ld.mc
, some RS runtime libs are given as inputs
to the linker. The RS bitcode from the app is linked against the runtime libs
and when the converted bitcode is loaded into an app process, the runtime libs
are again dynamically linked from the converted bitcode.
Runtime libs include:
libcompiler_rt.so
libm.so
libc.so
- RS driver (either
libRSDriver.so
orOVERRIDE_RS_DRIVER
)
When loading the compiled bitcode into the app process, provide the exact same
library that was used by ld.mc
. Otherwise, the compiled bitcode
may not find a symbol which was available when it was linked.
To do so, RS framework uses different search paths for the runtime libs when
executing ld.mc
, depending on whether the RS framework itself is
loaded from /system/lib
or from /system/lib/vndk-sp
.
This can be determined by reading the address of an arbitrary symbol of a RS
framework lib and using dladdr()
to get the file path mapped to
the address.
SELinux policy
As a result of the SELinux policy changes in Android 8.0 and higher, you must
follow specific rules (enforced through neverallows
) when
labelling additional files in vendor
partition:
vendor_file
must be the default label in for all files invendor
partition. The platform policy requires this to access passthrough HAL implementations.- All new
exec_types
added invendor
partition through vendor SEPolicy must havevendor_file_type
attribute. This is enforced throughneverallows
. - To avoid conflicts with future platform/framework updates, avoid labelling
files other than
exec_types
invendor
partition. - All library dependencies for AOSP-identified same process HALs must be
labelled as
same_process_hal_file
.
For details on SELinux policy, see Security-Enhanced Linux in Android.
ABI compatibility for bitcode
If no new APIs are added, which means no HAL version bump, the RS frameworks will keep using the existing GPU (HAL 1.0) driver.
For minor HAL changes (HAL 1.1) not affecting bitcode, the frameworks should fallback to CPU for these newly added APIs and keep using GPU (HAL 1.0) driver elsewhere.
For major HAL changes (HAL 2.0) affecting bitcode compilation/linking, RS frameworks should choose not to load vendor-provided GPU drivers and instead use the CPU or Vulkan path for acceleration.
Consuming RenderScript bitcode occurs in three stages:
Stage | Details |
---|---|
Compile |
|
Link |
|
Load |
|
In addition to the HAL, runtime APIs and the exported symbols are also interfaces. Neither interface has changed since Android 7.0 (API 24) and there are no immediate plans to change it in Android 8.0 and beyond. However, if the interface does change, the HAL version will also increment.
Vendor implementations
Android 8.0 and higher requires some GPU driver changes for the GPU driver to work correctly.
Driver modules
- Driver modules must not depend on any system libraries that are not in the list.
- Driver must provide its own
android.hardware.renderscript@1.0-impl_{NAME}
, or declare the default implementationandroid.hardware.renderscript@1.0-impl
as its dependency. - CPU implementation
libRSDriver.so
is a good example of how to remove non-VNDK-SP dependencies.
Bitcode compiler
You can compile RenderScript bitcode for the vendor driver in two ways:
- Invoke vendor-specific RenderScript compiler in
/vendor/bin/
(preferred method of GPU compilation). Similar to other driver modules, the vendor compiler binary cannot depend on any system library that is not in the list of RenderScript libs available to vendors. - Invoke system bcc:
/system/bin/bcc
with a vendor-providedbcc plugin
; this plugin cannot depend on any system library that is not in the list of RenderScript libs available to vendors.
If the vendor bcc plugin
needs to interfere with the CPU
compilation and its dependency on libLLVM.so
cannot be easily
removed, the vendor should copy bcc
(and all the non-LL-NDK
dependencies, including libLLVM.so
, libbcc.so
) into
/vendor
partition.
In addition, vendors need to make the following changes:
Figure 7. Changes to vendor driver.
- Copy
libclcore.bc
to/vendor
partition. This ensureslibclcore.bc
,libLLVM.so
, andlibbcc.so
are in sync. - Change the path to the
bcc
executable by settingRsdCpuScriptImpl::BCC_EXE_PATH
from the RS HAL implementation.
SELinux policy
SELinux policy affects both the driver and the compiler executables. All
driver modules must be labeled same_process_hal_file
in the
device's file_contexts
. For example:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
The compiler executable must be able to be invoked by an app process, as does
the vendor copy of bcc (/vendor/bin/bcc
). For example:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
Legacy devices
Legacy devices are those that satisfy the following conditions:
- PRODUCT_SHIPPING_API_LEVEL is lower than 26.
- PRODUCT_FULL_TREBLE_OVERRIDE is not defined.
For legacy devices, the restrictions are not enforced when upgrading to
Android 8.0 and higher, meaning the drivers can continue to link to libraries
in /system/lib[64]
. However, because of the architecture change
related to OVERRIDE_RS_DRIVER
,
android.hardware.renderscript@1.0-impl
must be installed to
/vendor
partition; failing to do so forces RenderScript runtime
fallback to CPU path.
For information about the motivation for the Renderscript deprecation, see the Android Developers Blog: Android GPU Compute Going Forward. Resource information for this deprecation includes the following:
- Migrate from Renderscript
- RenderScriptMigration Sample
- Intrinsics Replacement Toolkit README
- Intrinsics ReplacementToolkit.kt