Interacting with Nanoapps from Client Code

Code that interacts with a nanoapp, for example within an Android app, is known as the client of the nanoapp. There are two ways to interact with nanoapps from the host (application processor): (1) Java (above the Context Hub HAL, from the Android framework or an APK), and (2) native vendor code (beneath the Context Hub HAL). Most clients, especially those with a UI component, should use the Java method, unless a vendor-partition native implementation is required (e.g. if interacting with a nanoapp is used to implement a different HAL, or if communication with other beneath-HAL modules is required).

Interaction between nanoapps and clients occur through a flexible message passing interface. Refer to the Nanoapp Developer Guide for recommendations on how to design a protocol for use with a nanoapp.

Java APIs

CHRE is exposed to Android apps holding the appropriate permissions through the ContextHubManager and the associated ContextHubClient system APIs.

To use the above APIs, your application must have access to the ACCESS_CONTEXT_HUB permission, which is restricted to signature|privileged. This permission must be declared in the app’s Android Manifest, and is only granted to APKs that are signed with the same key as the platform (“signature” scope) or are preinstalled in the privileged apps folder and are present on the privileged permission allowlist.

The recommended flow for Java nanoapp client code is as follows:

  1. Retrieve the ContextHubManager object via Context.getSystemService(ContextHubManager.class) - this will produce a valid handle if the device supports FEATURE_CONTEXT_HUB as indicated by PackageManager.hasSystemFeature()
  2. Retrieve a reference to a Context Hub via ContextHubManager.getContextHubs()
  3. Confirm that the nanoapp is loaded and retrieve its version number by calling ContextHubManager.queryNanoApps()
  4. If the nanoapp was found, create a ContextHubClient object through ContextHubManager.createClient(). This can be used to communicate with your nanoapp, and receive notifications of system events like reset. Note that the createClient() API supports two modes of operation, which define how events and data are passed to the client: direct callback with ContextHubClientCallback (requires a persistent process), or PendingIntent with ContextHubIntentEvent (can start an app’s process when an event occurs). To send messages to the nanoapp, use ContextHubClient.sendMessageToNanoApp().

Vendor Native

Depending on the details of the platform implementation, you may also be able to interact with CHRE directly, beneath the Context Hub HAL, by using socket IPC as exposed by the CHRE daemon reference implementation. This approach has some advantages, like being able to interact with system nanoapps that are not exposed at the Java level, and it can be used with other low-level beneath-HAL code. However, it is not suitable for use from native code within an Android app.

See host/common/test/ for an example of how to use this interface. Note that SELinux configuration is generally required to allowlist access to the CHRE socket.