Runtime

The Runtime module (com.android.runtime.release.apex) is an APEX module for native and managed Android runtimes. The module includes the following components:

  • ART
  • Bionic
  • Managed Core Library (new in Android 10)
  • ICU libraries
  • libnativebridge
  • libnativehelper
  • libnativeloader

The Runtime module is generated when building Android and contains the build artifacts of its constituent projects. It's closely coupled with both the Conscrypt module (com.android.conscrypt.apex) and the Time Zone Data module (com.android.tzdata.apex), also new in Android 10.

Android Runtime (ART) changes

In Android 10, the ART build system creates the Runtime module in two variants: release and debug (contains additional diagnostic and debugging tools). The release version is installed on user builds and the debug version is installed on userdebug and eng builds. When a device boots, apexd mounts the Runtime module under /apex/com.android.runtime.

In the module, the boot class path is split between classes such as Managed Core Library, classes in other modules (such as Conscrypt and Media), and classes in the system partition (such as framework.jar). If a module is updated, dex2oat JIT compiles boot classes in modules.

Android 10 includes the following API changes:

  • A new API for DEX file support provides a stable interface between system code (such as the stack unwinder) and ART.
  • A new API is used as an ART-specific platform abstraction layer (PAL) with the system. The system element (libartpalette-system.so) exposes system functionality depended on by ART and is accessible through a client library (libartpalette.so), that loads the system library installed on device.

Android 10 also refactors paths for some ART binaries, moving the following binaries from /system/bin to the Runtime module: dalvikvm, dalvikvm32, dalvikvm64, dex2oat, dexdiag, dexdump, dexlist, dexoptanalyzer, oatdump, and profman. For compatibility, the refactor includes symlinks in /system/bin.

Bionic changes

libc's tzcode uses time zone data provided by the Runtime module (/apex/com.android.runtime/etc/tz/) and the Time Zone Data module (/apex/com.android.tzdata/etc/tz/). tzcode prioritizes data from APK-based time zone updates over APEX-based time zone updates (provided by the Time Zone Data module) and falls back to /system data.

libc uses a new library (libandroidicu) instead of libicuuc/libicui18n. For details, see Managed Core Library.

Finally, Bionic-shared libraries and dynamic linker paths are now symlinks (applies to 64-bit variants as well). Specifically:

  • /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so
  • /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so
  • /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so
  • /system/bin/linker -> /apex/com.android.runtime/bin/linker

Boot sequence changes

To support the Runtime module, Android 10 updates the boot sequence to the following:

  1. init prepares the bootstrap and default mount namespaces. A tmpfs is mounted on /apex and the propagation type of the mount point is set to private.
  2. apexd starts in bootstrap mode, before any other process. It activates the APEX files in /system/apex and mounts them in the bootstrap mount namespace.
  3. Other pre-apexd processes start. These processes are in the bootstrap mount namespace and are provided with libraries from system APEX files.
  4. /data mounts. init switches into the default mount namespace and starts apexd as a daemon.
  5. apexd scans both /data/apex and /system/apex and activates the most recent APEX files in those directories. APEX files activated in this phase are mounted in the default namespaces only and aren't visible to the pre-apexd processes.

Managed Core Library

The Managed Core Library is a collection of low-level, updatable, managed (dex executed by Android Runtime) code that was previously known as libcore. In Android 10, the Managed Core Library includes multiple Git projects (in addition to platform/libcore/), and the new term refers to the collection of code.

The Managed Core Library is provided by the Runtime, Time Zone Data, and Conscrypt modules and relies on native libraries present in the Runtime module, such as libjavacore and libandroidicu. Collected code comes from multiple Git projects such as libcore, apache-xml, boringssl, bouncycastle, conscrypt, expat, fdlibm, icu, okhttp, ziparchive, and zlib. The library is split between multiple .jar files on the boot classpath (for example core-oj.jar, core-libart.jar, conscrypt.jar, okhttp.jar, bouncycastle.jar, and apache-xml.jar); however, it doesn't include framework.jar or ext.jar.

Component repackaging

Android 10 repackages several components (bouncycastle/, conscrypt/, okhttp/) that were previously packaged under android.* and com.android.* using bytecode manipulation. These components are repackaged using source code transformation to enable Java annotations to be used for API metadata.

Core Platform API

The Core Platform API provides a stable, managed-code API for use by the Android framework, enabling the Managed Core Library to be updated by ensuring that all framework dependencies are clearly understood. The Core Platform API:

  • Indicates dependencies in addition to the public SDK APIs. For API content, refer to libcore/mmodules/core_platform_api/.
  • Explicitly annotates managed code with @libcore.api.CorePlatformApi. For code in libcore/ojluni/src/, refer to the annotations in libcore/ojluni/annotations/mmodule/; for all other projects, refer to the main source files.

The build system defaults to using the Core Platform API when building Java source platform targets (that is, in the absence of "sdk_version:" in .bp files or "LOCAL_SDK_VERSION=" in .mk files). This default ensures that Android framework code is restricted to using public APIs and the Core Platform API only (no implementation classes). Other sdk_version values such as "core_current" and "current" work as they always have (they allow use of public SDK APIs only). The build system also reports changes to the Core Platform API surface and prevents targets (outside of a small set of exceptions) from depending on Managed Core Library internals.

The Runtime module performs access checks for fields and methods covered by the Core Platform API. The checks are performed when platform code accesses methods in the Core Platform API. The system property persist.debug.dalvik.vm.core_platform_api_policy controls the policy around these checks. Valid policy values are enabled, disabled, and just-warn. For debug and eng builds, the standard policy is just-warn, which logs a warning when a policy violation is detected. For user builds, the default policy is disabled and no action is taken. The Runtime module also performs Core Platform API checks when native code resolves fields and methods through the Java Native Interface (JNI).

Android 10 also includes numerous changes to simplify the APIs, runtime dependencies, and build-time dependencies between the Android framework and Managed Core Library.

Android 10 repackages the org.kxml2 parser under com.android.org.kxml2.

Native libraries

Android 10 refactors native libraries that support the Managed Core Library. Several dynamically linked libraries (for example, libcrypto, libexpat, and zlib) that were previously shared with other parts of the platform are now duplicated so that the Runtime module has its own copies loaded into the runtime linker namespace. Dynamically linked native libraries provided by the Runtime module are in /apex/com.android.runtime/{lib,lib64}.

ICU libraries

The Runtime module includes ICU libraries (ICU4C and ICU4J) and associated data.

Android 10 includes libandroidicu, a new dynamic library that makes a subset of ICU4C functions available to framework code. The linker symbols for libandroidicu are stable across ICU releases (the symbols end with _android rather than _icu-version-number used in libicuuc and libicui18n). However, for app compatibility, libicuuc and libicui18n symbols remain available. Also for app compatibility, the linker redirects absolute paths to ICU libraries in dlopen() calls, i.e. dlopen("/system/lib/libicuuc.so", ...) and dlopen("/system/lib/libicui18n.so", ...), redirect to the corresponding libraries in /apex/com.android.runtime/lib/ for apps with targetSdkVersion < 29.

At runtime, the ICU data file installs to /apex/com.android.runtime/etc/icu/. For app compatibility, Android 10 includes a symlink from the previous ICU data file location (/system/usr/icu/) to /apex/com.android.runtime/etc/icu.

Conscrypt interactions

Android 10 moves Conscrypt, which is logically part of the Managed Core Library, to its own independently updatable APEX module. Between the Conscrypt and Runtime modules, a new bi-directional API surface indicates dependencies in addition to the public SDK APIs (for details, refer to libcore/mmodules/intracoreapi/). API elements are explicitly annotated with @libcore.api.IntraCoreApi.

The build system verifies that Conscrypt code is restricted to public APIs and the intra-core API. Other Managed Core Library dependencies on Conscrypt are reflection based; the build system records such dependencies where possible and reports all changes to the API surface.

Time Zone Data interactions

In Android 10, architecture libcore, Runtime libcore, and ICU4J/ICU4C use time zone data provided by the Runtime module (/apex/com.android.runtime/etc/tz/) and the Time Zone Data module (/apex/com.android.tzdata/etc/tz/). These libraries:

Miscellaneous changes

Android 10 moves the AsynchronousCloseMonitor API from libnativehelper.so to libandroidio.so. The API is exposed by AsynchronousCloseMonitor.h.

libnativebridge changes

Android 10 moves the libnativebridge library to the Runtime module as this library is tightly coupled with libnativeloader and the Bionic C libraries that are part of the Runtime module.

libnativehelper changes

In Android 10, the Runtime module makes libnativehelper available to system and frameworks code, while code outside of the Runtime module links against a stubs API (C only) for libnativehelper. The libnativehelper library includes:

  • A reduced set of cached JNI classes, methods, and fields.
  • Improved JNI macros in platform_include/jni_macros.h.
  • New JNI helper methods for accessing the internals of java.nio.Buffer classes from native code (see methods starting with jniGetNio in libnativehelper/include/nativehelper/JNIHelp.h). These methods are used by the framework code.

libnativeloader changes

In Android 10, the Runtime module includes the libnativeloader library, which is responsible for creating linker namespaces for Java class loaders. The linker namespaces apply to the native libraries loaded by Android apps written in managed code. The library is closely coupled to the Bionic linker, which is also in the module.

libpac changes

Android 10 moves libpac, which provides a C API for PacProcessor, into the Runtime module. The libpac library contains an entire V8 JavaScript engine and should not be used except by PacProcessor (an independent package and process).

Linker configuration changes

In Android 10, linker namespaces are used to separate internal dynamic native library dependencies in the Runtime module from the platform and other APEX modules. The runtime linker namespace is set up for Runtime module libraries, with appropriate links to and from other namespaces for external dependencies.

The linker configuration resides in /system/etc/ld.config.txt for binaries in /vendor and /system, and in /apex/com.android.runtime/etc/ld.config.txt for binaries in the Runtime module itself (/apex/com.android.runtime/bin).

SystemServer and framework changes

In Android 10, the SystemServer hosts a new RuntimeService for reporting information from the Runtime module. To view this information, use the following ADB command:

adb shell dumpsys runtimeinfo

The information managed by the RuntimeService is extensible. For service source code, refer to frameworks/base/services/core/java/com/android/server/RuntimeService.java; for example client code, refer to libcore/luni/src/main/java/libcore/util/CoreLibraryDebug.java.

Android 10 also updates the over-the-air (OTA) update process to use dex2oat and other tools from the Runtime module.