| # Interacting with Nanoapps from Client Code |
| |
| [TOC] |
| |
| 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](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/hardware/location/ContextHubManager.java) |
| and the associated |
| [ContextHubClient](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/hardware/location/ContextHubClient.java) |
| 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](https://developer.android.com/guide/topics/manifest/uses-permission-element), |
| 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](https://source.android.com/devices/tech/config/perms-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/chre_test_client.cc` for an example of how to use this |
| interface. Note that SELinux configuration is generally required to allowlist |
| access to the CHRE socket. |
| |