Context Hub Runtime Environment (CHRE)

Smartphones contain a number of processors, each optimized for performing different tasks. However, Android only runs on one processor: the applications processor (AP). The AP is tuned for delivering great performance for screen-on use cases such as gaming, but it's too power hungry to support features that require frequent, short bursts of processing all the time, even when the screen is off. Smaller processors are able to handle these workloads more efficiently, completing their tasks without noticeably impacting battery life. However, the software environments in these low-power processors are more limited and can vary greatly, making cross-platform development difficult.

Context Hub Runtime Environment (CHRE) provides a common platform for running apps on a low-power processor, with a simple, standardized, embedded-friendly API. CHRE makes it easy for device OEMs and their trusted partners to offload processing from the AP, to save battery and improve various areas of the user experience, and enable a class of always-on, contextually aware features, especially those involving the application of machine learning to ambient sensing.

Key concepts

CHRE is the software environment where small native applications, called nanoapps, execute on a low-power processor and interact with the underlying system through the common CHRE API. To accelerate proper implementation of the CHRE APIs, a cross-platform reference implementation of CHRE is included in AOSP. The reference implementation includes common code and abstractions to the underlying hardware and software through a series of platform abstraction layers (PALs). Nanoapps are almost always tied to one or more client apps running in Android, which interact with CHRE and nanoapps through restricted-access ContextHubManager system APIs.

At a high level, parallels can be drawn between the architecture of CHRE and Android as a whole. However, there are a few important distinctions:

  • CHRE supports running only nanoapps developed in native code (C or C++); Java isn't supported.
  • Due to resource constraints and security limitations, CHRE isn't open for use by arbitrary third-party Android apps. Only system-trusted apps can access it.

There's also an important distinction to be made between the concept of CHRE and a sensor hub. While it's common to use the same hardware to implement the sensor hub and CHRE, CHRE itself doesn't provide the sensor functionality required by the Android Sensors HAL. CHRE is tied to the Context Hub HAL, and it acts as a client of a device-specific sensor framework to receive sensor data without involving the AP.

CHRE framework architecture

Figure 1. CHRE framework architecture

Context Hub HAL

The Context Hub hardware abstraction layer (HAL) is the interface between the Android framework and the device's CHRE implementation, defined at hardware/interfaces/contexthub. The Context Hub HAL defines the APIs through which the Android framework discovers available context hubs and their nanoapps, interacts with those nanoapps through message passing, and allows for nanoapps to be loaded and unloaded. A reference implementation of the Context Hub HAL that works with the reference implementation of CHRE is available at system/chre/host.

In the event of conflict between this documentation and the HAL definition, the HAL definition takes precedence.

Initialization

When Android boots up, the ContextHubService invokes the getHubs() HAL function to determine if any context hubs are available on the device. This is a blocking, one-time call, so it must complete quickly to avoid delaying boot, and it must return an accurate result, as new context hubs can't be introduced afterward.

Loading and unloading nanoapps

A context hub can include a set of nanoapps that are included in the device image and are loaded when CHRE starts. These are known as preloaded nanoapps, and should be included in the first possible response to queryApps().

The Context Hub HAL also supports loading and unloading nanoapps dynamically at runtime, through the loadNanoApp() and unloadNanoApp() functions. Nanoapps are provided to the HAL in a binary format specific to the CHRE hardware and software implementation of the device.

If the implementation for loading a nanoapp involves writing it to nonvolatile memory, such as flash storage attached to the processor that runs CHRE, then the CHRE implementation must always boot up with these dynamic nanoapps in the disabled state. This means that none of the nanoapp's code is executed until an enableNanoapp() request is received through the HAL. Preloaded nanoapps can initialize in the enabled state.

Context hub restarts

While CHRE isn't expected to restart during the course of normal operation, it can be necessary to recover from unexpected conditions such as an attempt to access an unmapped memory address. In these situations, CHRE restarts independently from Android. The HAL notifies Android of this through the RESTARTED event, which it must send only after CHRE has been reinitialized to the point that it can accept new requests, such as queryApps().

CHRE system overview

CHRE is designed around an event-driven architecture, where the primary unit of computation is an event passed to a nanoapp's event handling entry point. While the CHRE framework can be multithreaded, a given nanoapp is never executed from multiple threads in parallel. The CHRE framework interacts with a given nanoapp through one of the three nanoapp entry points (nanoappStart(), nanoappHandleEvent(), and nanoappEnd()) or through a callback provided in a prior CHRE API call, and nanoapps interact with the CHRE framework and the underlying system through the CHRE API. The CHRE API provides a set of basic functionality as well as facilities for accessing contextual signals, including sensors, GNSS, Wi-Fi, WWAN, and audio, and it can be extended with additional vendor-specific capabilities for use by vendor-specific nanoapps.

Build system

While the Context Hub HAL and other necessary AP-side components are built alongside Android, code that runs within CHRE can have requirements that make it incompatible with the Android build system, such as the need for a specialized toolchain. Therefore, the CHRE project in AOSP provides a simplified build system based on GNU Make to compile nanoapps, and, optionally, the CHRE framework into libraries that can be integrated with the system. Device manufacturers adding support for CHRE should integrate build system support for their target devices into AOSP.

The CHRE API is written to the C99 language standard, and the reference implementation uses a restricted subset of C++11 suitable for resource-limited applications.

CHRE API

The CHRE API is a collection of C header files that define the software interface between a nanoapp and the system. It's designed to make nanoapps code compatible across all devices that support CHRE, which means that the source code for a nanoapp doesn't need to be modified to support a new device type, though it might need to be recompiled specifically for the target device's processor instruction set or application binary interface (ABI). The CHRE architecture and API design also ensure that nanoapps are binary compatible across different versions of the CHRE API, which means that a nanoapp doesn't need to be recompiled to run on a system that implements a different version of the CHRE API as compared to the target API that the nanoapp is compiled against. In other words, if a nanoapp binary runs on a device that supports CHRE API v1.3, and that device is upgraded to support CHRE API v1.4, the same nanoapp binary continues to function. Similarly, the nanoapp can run on CHRE API v1.2, and can determine at runtime whether it requires functionality from API v1.3 to achieve its functionality, or whether it can operate, potentially with graceful feature degradation.

New versions of the CHRE API are released alongside Android, however as the CHRE implementation is part of the vendor implementation, the CHRE API version supported on a device isn't necessarily linked to an Android version.

Version summary

Like the Android HIDL versioning scheme, the CHRE API follows semantic versioning. The major version indicates binary compatibility, while the minor version is incremented when backward-compatible features are introduced. The CHRE API includes source code annotations to identify which version introduced a function or parameter, for example @since v1.1.

The CHRE implementation also exposes a platform-specific patch version through chreGetVersion(), which indicates when bug fixes or minor updates are made in the implementation.

Version 1.0 (Android 7)

Includes support for sensors, and core nanoapp functionality, such as events and timers.

Version 1.1 (Android 8)

Introduces location capabilities through GNSS location and raw measurements, Wi-Fi scanning, and cellular network information, along with general refinements to enable nanoapp-to-nanoapp communication, and other improvements.

Version 1.2 (Android 9)

Adds support for data from a low-power microphone, Wi-Fi RTT ranging, AP wake/sleep notifications, and other improvements.

Version 1.3 (Android 10)

Enhances capabilities related to sensor calibration data, adds support for flushing batched sensor data on demand, defines the step detect sensor type, and extends GNSS location events with additional accuracy fields.

Version 1.4 (Android 11)

Adds support for 5G cell information, nanoapp debug dump, and other improvements.

Mandatory system features

While sources of contextual signals, like sensors, are categorized into optional feature areas, a few core functions are required across all CHRE implementations. This includes core system APIs, such as those for setting timers, sending and receiving messages to clients on the applications processor, logging, and others. For full details, see the API headers.

In addition to the core system features codified in the CHRE API, there are also mandatory CHRE system-level features specified at the Context Hub HAL level. The most significant of these is the ability to dynamically load and unload nanoapps.

C/C++ standard library

To minimize memory usage and system complexity, CHRE implementations are required to support only a subset of the standard C and C++ libraries and language features requiring runtime support. Following these principles, some features are explicitly excluded due to their memory and/or extensive OS-level dependencies, and others because they're supplanted by more suitable CHRE-specific APIs. While not meant to be an exhaustive list, the following capabilities aren't intended to be made available to nanoapps:

  • C++ exceptions and runtime type information (RTTI)
  • Standard library multithreading support, including C++11 headers <thread>, <mutex>, <atomic>, <future>
  • C and C++ Standard Input/Output libraries
  • C++ Standard Template Library (STL)
  • C++ Standard Regular Expressions library
  • Dynamic memory allocation through standard functions (for example, malloc, calloc, realloc, free, operator new), and other standard library functions that inherently use dynamic allocation, such as std::unique_ptr
  • Localization and Unicode character support
  • Date and time libraries
  • Functions that modify normal program flow, including <setjmp.h>, <signal.h>, abort, std::terminate
  • Accessing the host environment, including system, getenv
  • POSIX and other libraries not included in the C99 or C++11 language standards

In many cases, equivalent functionality is available from CHRE API functions and/or utility libraries. For example, chreLog can be used for debug logging targeted to the Android logcat system, where a more traditional program might use printf or std::cout.

In contrast, some standard library functionality is required. It's up to the platform implementation to expose these through static libraries for inclusion in a nanoapp binary, or by dynamic linking between the nanoapp and system. This includes, but is not limited to:

  • String/array utilities: memcmp, memcpy, memmove, memset, strlen
  • Math library: Commonly used single-precision floating-point functions:

    • Basic operations: ceilf, fabsf, floorf, fmaxf, fminf, fmodf, roundf, lroundf, remainderf
    • Exponential/power functions: expf, log2f, powf, sqrtf
    • Trigonometric/hyperbolic functions: sinf, cosf, tanf, asinf, acosf, atan2f, tanhf

While some underlying platforms support additional functionality, a nanoapp isn't considered portable across CHRE implementations unless it constrains its external dependencies to CHRE API functions and approved standard library functions.

Optional features

To promote hardware and software, the CHRE API is divided into feature areas, which are considered optional from the API perspective. While these features might not be required to support a compatible CHRE implementation, they might be required to support a particular nanoapp. Even if a platform doesn't support a given set of APIs, nanoapps that reference those functions must be able to build and load.

Sensors

The CHRE API provides the ability to request data from sensors including accelerometer, gyroscope, magnetometer, ambient light sensor, and proximity. These APIs are meant to provide a feature set similar to the Android Sensors APIs, including support for batching sensor samples to reduce power consumption. Processing sensor data within CHRE enables much lower power and lower latency processing of motion signals as compared to running on the AP.

GNSS

CHRE supplies APIs for requesting location data from a global navigation satellite system (GNSS), including GPS and other satellite constellations. This includes requests for periodic position fixes, as well as raw measurement data, though both are independent capabilities. As CHRE has a direct link to the GNSS subsystem, power is reduced compared to AP-based GNSS requests, because the AP can stay asleep during the entire lifecycle of a location session.

Wi-Fi

CHRE provides the ability to interact with the Wi-Fi chip, primarily for location purposes. While GNSS works well for outdoor locations, the results of Wi-Fi scans can provide accurate location information indoors and in developed areas. In addition to avoiding the cost of waking the AP for a scan, CHRE can listen to the results of Wi-Fi scans performed by the Wi-Fi firmware for connectivity purposes, which typically aren't delivered to the AP for power reasons. Leveraging connectivity scans for contextual purposes helps to reduce the total number of Wi-Fi scans performed, saving power.

Support for Wi-Fi was added in CHRE API v1.1, including the ability to monitor scan results and trigger scans on demand. These capabilities were extended in v1.2 with the ability to perform Round-Trip Time (RTT) measurements against access points that support the feature, which enables accurate relative position determination.

WWAN

The CHRE API provides the ability to retrieve cell identification information for the serving cell and its neighbors, which is typically used for coarse-grained location purposes.

Audio

CHRE can process batches of audio data from a low-power microphone, which typically leverages hardware used to implement the SoundTrigger HAL. Processing audio data in CHRE can enable it to be fused with other data, such as motion sensors.

Reference implementation

Reference code for the CHRE framework is included in AOSP in the system/chre project, implemented in C++11. While not strictly required, it's recommended for all CHRE implementations to be based off of this codebase, to help ensure consistency and accelerate adoption of new capabilities. This code can be seen as an analogue to the core Android framework in that it's an open-source implementation of APIs that applications use, serving as a baseline and standard for compatibility. While it can be customized and extended with vendor-specific capabilities, the recommendation is to maintain the common code as close to the reference as possible. Similar to the HALs of Android, the CHRE reference implementation uses various platform abstractions to enable it to be adapted to any device meeting the minimum requirements.

For technical details and a porting guide, see the README included in the system/chre project.