|
|
|
|
*** aside
|
|
|
|
|
See also: [Nanoapp Developer Guide](/doc/nanoapp_developer_guide.md) |
|
|
|
|
|
[Interacting with Nanoapps](/doc/nanoapp_clients.md)
|
|
|
|
|
***
|
|
|
|
|
|
|
|
|
|
# Nanoapp Overview
|
|
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
|
|
|
|
Nanoapps are applications written in C or C++ which run in CHRE, to leverage
|
|
|
|
|
low-power hardware. Typically, nanoapps integrate with a component on the
|
|
|
|
|
Android side, such as a privileged APK, in order to provide complete end-to-end
|
|
|
|
|
functionality of the target feature. This Android-side component is referred to
|
|
|
|
|
as the nanoapp’s “client”. Since nanoapps are not limited to the same power
|
|
|
|
|
constraints that Android apps are, they can process inputs, like sensor data,
|
|
|
|
|
much more frequently while the device’s screen is off.
|
|
|
|
|
|
|
|
|
|
Nanoapps are abstracted from the underlying platform details by the CHRE API,
|
|
|
|
|
which is standardized across all CHRE implementations. This means that a nanoapp
|
|
|
|
|
is *code compatible* across devices - its source code does not need to be
|
|
|
|
|
changed to run on different hardware, but it *may* need to be recompiled. The
|
|
|
|
|
CHRE API also provides binary compatibility guarantees across minor versions, so
|
|
|
|
|
a nanoapp does not need to be recompiled to run on a device that exposes a newer
|
|
|
|
|
or older version of the CHRE API. These properties help provide for the maximum
|
|
|
|
|
reuse of code across devices.
|
|
|
|
|
|
|
|
|
|
Due to system security and resource constraints of the platforms that CHRE
|
|
|
|
|
targets, only device OEMs and their trusted partners are able to create
|
|
|
|
|
nanoapps. In other words, the system only runs nanoapps that possess a digital
|
|
|
|
|
signature that is trusted in advance by the device manufacturer, and APKs must
|
|
|
|
|
hold a special privileged/same-signature permission (`ACCESS_CONTEXT_HUB`) to be
|
|
|
|
|
able to interact with nanoapps and the Context Hub in general. However, this
|
|
|
|
|
does not mean that third-party APKs cannot benefit from CHRE - nanoapps can be
|
|
|
|
|
used to power APIs available for use by any Android app.
|
|
|
|
|
|
|
|
|
|
## Methods for Loading a Nanoapp
|
|
|
|
|
|
|
|
|
|
While nanoapps are nominally dynamically loadable modules, they can be loaded
|
|
|
|
|
into a device through a few methods, each of which has pros and cons elaborated
|
|
|
|
|
below.
|
|
|
|
|
|
|
|
|
|
### Static Nanoapps
|
|
|
|
|
|
|
|
|
|
Static nanoapps are, as the name suggests, statically compiled into the CHRE
|
|
|
|
|
framework binary. Static nanoapps are automatically initialized after the CHRE
|
|
|
|
|
framework completes its initialization during the boot process.
|
|
|
|
|
|
|
|
|
|
Static nanoapps typically aren’t used in production, because this monolithic
|
|
|
|
|
approach has downsides in terms of version control, updatability, etc., but it
|
|
|
|
|
can be useful during CHRE development and bring-up of new devices, especially
|
|
|
|
|
before dynamic loading functionality is enabled. For example, the FeatureWorld
|
|
|
|
|
nanoapps (described later) are typically built as static nanoapps.
|
|
|
|
|
|
|
|
|
|
Static nanoapps are typically unconditionally compiled as part of the framework
|
|
|
|
|
build (via `apps/apps.mk`), but then stripped out by the linker if unreferenced
|
|
|
|
|
(using the `--gc-sections` option, or equivalent). Static nanoapps are
|
|
|
|
|
referenced only if their initialization function appears in the
|
|
|
|
|
`kStaticNanoappList` array, which by default is empty, but can be overridden by
|
|
|
|
|
the device variant makefile, as in `variant/simulator/` for example.
|
|
|
|
|
|
|
|
|
|
Some boilerplate is needed to enable nanoapp to be built as a static nanoapp -
|
|
|
|
|
see the code wrapped in `#ifdef CHRE_NANOAPP_INTERNAL` in
|
|
|
|
|
`apps/hello_world/hello_world.cc`.
|
|
|
|
|
|
|
|
|
|
### Preloaded Nanoapps
|
|
|
|
|
|
|
|
|
|
Preloaded nanoapps are built as a separate binary from the CHRE framework, but
|
|
|
|
|
included in the vendor partition of an overall device image (hence they are
|
|
|
|
|
“preloaded” onto the device). The binaries associated with a preloaded nanoapp
|
|
|
|
|
(usually a `.so` and a `.napp_header` file) are checked in to the Android tree
|
|
|
|
|
as a “prebuilt” binary, and integrated into the Android build system so as to
|
|
|
|
|
appear in the resulting device image, for example using `$(BUILD_PREBUILT)` in
|
|
|
|
|
Android.mk, or `prebuilt_dsp` or `prebuilt_firmware` in Android.bp.
|
|
|
|
|
|
|
|
|
|
While the mechanism for loading prebuilt nanoapps is platform-specific, the CHRE
|
|
|
|
|
framework generally follows these steps at boot time:
|
|
|
|
|
|
|
|
|
|
1. When CHRE starts up, the CHRE daemon process running on the AP reads the
|
|
|
|
|
configuration file `/vendor/etc/chre/preloaded_nanoapps.json`, which contains
|
|
|
|
|
the list of nanoapps that should be automatically loaded.
|
|
|
|
|
|
|
|
|
|
2. For each nanoapp in the JSON file, the CHRE daemon reads the `.napp_header`
|
|
|
|
|
from storage, and sends a message to CHRE requesting it to load the nanoapp.
|
|
|
|
|
|
|
|
|
|
3. The platform layer of the CHRE framework handles the requests by loading,
|
|
|
|
|
authenticating, linking, and starting the nanoapp.
|
|
|
|
|
|
|
|
|
|
4. CHRE initialization proceeds (it is important for all preloaded nanoapps to
|
|
|
|
|
be included at the first moment list query command can be processed, to
|
|
|
|
|
avoid race conditions leading to clients believing that a preloaded nanoapp
|
|
|
|
|
is missing).
|
|
|
|
|
|
|
|
|
|
This path is most commonly used to deploy nanoapps to production, as the entire
|
|
|
|
|
device software can be validated together without external dependencies, while
|
|
|
|
|
also preserving the ability to update nanoapps independent from other components
|
|
|
|
|
in the system.
|
|
|
|
|
|
|
|
|
|
### Fully Dynamic Nanoapps
|
|
|
|
|
|
|
|
|
|
At the binary level, a preloaded nanoapp and fully dynamic nanoapp are
|
|
|
|
|
identical. The key difference is where they are stored and how they are
|
|
|
|
|
initially loaded into CHRE, and potentially how metadata is handled. In most
|
|
|
|
|
cases, preloaded nanoapps will use a separate `.napp_header` file with metadata
|
|
|
|
|
and `.so` file for the actual binary, a fully dynamic nanoapp has the header
|
|
|
|
|
prepended to the binary, and carries the `.napp` file type suffix. In other
|
|
|
|
|
words, the command `cat my_nanoapp.napp_header my_nanoapp.so > my_nanoapp.napp`
|
|
|
|
|
can be used to create a fully dynamic nanoapp file from these components.
|
|
|
|
|
|
|
|
|
|
Instead of being stored on the device filesystem, fully dynamic nanoapps can be
|
|
|
|
|
loaded at any time after initialization using the
|
|
|
|
|
`ContextHubManager.loadNanoApp()` Java API. This allows nanoapps to be
|
|
|
|
|
updated/delivered by an APK, outside of a full Android system update (OTA).
|
|
|
|
|
|
|
|
|
|
This mechanism is used to dynamically load and unload test nanoapps, but can
|
|
|
|
|
also be used for production nanoapps.
|
|
|
|
|
|
|
|
|
|
## Other Nanoapp Types
|
|
|
|
|
|
|
|
|
|
Some platforms support loading nanoapps into multiple tiers of memory, for
|
|
|
|
|
example low-power tightly coupled memory (TCM, usually SRAM), versus a
|
|
|
|
|
higher-power but higher-capacity memory bank (such as DRAM). This distinction is
|
|
|
|
|
normally made at the build target variant level.
|
|
|
|
|
|
|
|
|
|
CHRE also supports the concept of a *system nanoapp*, which is a nanoapp whose
|
|
|
|
|
purpose is to accomplish some low-level, device-specific functionality that is
|
|
|
|
|
purely beneath the HAL level. System nanoapps are therefore hidden from the
|
|
|
|
|
nanoapp list at the HAL. This property is controlled by setting the
|
|
|
|
|
`NANOAPP_IS_SYSTEM_NANOAPP` variable in the nanoapp Makefile.
|
|
|
|
|
|
|
|
|
|
## Example AOSP Nanoapps
|
|
|
|
|
|
|
|
|
|
Some basic nanoapps can be found in the `apps/` folder, which are used for test
|
|
|
|
|
purposes, as well as to demonstrate how to use the CHRE APIs.
|
|
|
|
|
|
|
|
|
|
### FeatureWorld Nanoapps
|
|
|
|
|
|
|
|
|
|
The *FeatureWorld* nanoapps each exercise a part of the CHRE API, and print
|
|
|
|
|
results/output to `chreLog`. An overview of a few of the key FeatureWorld
|
|
|
|
|
nanoapps is given below:
|
|
|
|
|
|
|
|
|
|
* `hello_world`: While not technically a FeatureWorld nanoapp, it’s generally
|
|
|
|
|
the first nanoapp to be tried, and it simply outputs a log message when it
|
|
|
|
|
starts and ends, and upon any event received.
|
|
|
|
|
|
|
|
|
|
* `message_world`: Exercises host messaging functionality. Typically used in
|
|
|
|
|
conjunction with `host/common/test/chre_test_client.cc` (see
|
|
|
|
|
`sendMessageToNanoapp()` in that file).
|
|
|
|
|
|
|
|
|
|
* `sensor_world`: Enables sensors and prints the samples it receives. This
|
|
|
|
|
nanoapp is typically customized prior to executing, for example to control
|
|
|
|
|
which sensors it will enable. It also supports a “break it” mode which
|
|
|
|
|
stresses the system by enabling/disabling sensors frequently.
|
|
|
|
|
|
|
|
|
|
* `host_awake_world`: Used to help validate functionality used for
|
|
|
|
|
opportunistically sending messages to the AP when it is awake.
|
|
|
|
|
|
|
|
|
|
### Stress Test Nanoapps
|
|
|
|
|
|
|
|
|
|
These nanoapps help stress test the CHRE framework. They include:
|
|
|
|
|
|
|
|
|
|
* `audio_stress_test`: Repeatedly enables and disables an audio source,
|
|
|
|
|
verifying that it continues to provide data as expected.
|
|
|
|
|
|
|
|
|
|
* `sensor_world`: Contains a “break it” mode which repeatedly enables, disables,
|
|
|
|
|
and reconfigures sensors.
|
|
|
|
|
|
|
|
|
|
* `spammer`: Sends a constant stream of messages and events to stress test the
|
|
|
|
|
queueing system.
|
|
|
|
|
|
|
|
|
|
* `unload_tester`: Used in conjunction with the spammer nanoapp to verify that
|
|
|
|
|
unloading a nanoapp with pending events/messages completes successfully. Note
|
|
|
|
|
that this nanoapp references internal framework functions (e.g.
|
|
|
|
|
`EventLoopManager::deferCallback()`) to accomplish its functionality, which is
|
|
|
|
|
generally only permissible for testing purposes.
|
|
|
|
|
|
|
|
|
|
### Power Test
|
|
|
|
|
|
|
|
|
|
The `power_test` nanoapp is intended to be used in conjunction with special
|
|
|
|
|
hardware that directly measures the power usage of the system and/or its
|
|
|
|
|
components. This nanoapp is intended to be used with its host-side client,
|
|
|
|
|
`chre_power_test_client`, to create some activity at the CHRE API level which
|
|
|
|
|
can then be measured. For example, running `./chre_power_test_client wifi enable
|
|
|
|
|
5000000000` will configure the `power_test` nanoapp to request a WiFi scan every
|
|
|
|
|
5 seconds - the power monitoring equipment can then be used to determine the
|
|
|
|
|
power cost of performing a WiFi scan from CHRE. Typically this is done after
|
|
|
|
|
unloading all other nanoapps in the system (which can be done via
|
|
|
|
|
`./chre_power_test_client unloadall`), and disabling all other functionality, to
|
|
|
|
|
get a clean power trace of purely the functionality exercised by the
|
|
|
|
|
`power_test` nanoapp.
|
|
|
|
|
|
|
|
|
|
Refer to `chre_power_test_client.cc` for more details, including a full listing
|
|
|
|
|
of all supported commands.
|
|
|
|
|
|
|
|
|
|
### Nanoapps Used with Java-based Test Suites
|
|
|
|
|
|
|
|
|
|
Nanoapps under `apps/test` are associated with a test suite, for example Context
|
|
|
|
|
Hub Qualification Test Suite (CHQTS), which is used to test that a given device
|
|
|
|
|
upholds the requirements of the CHRE API. Much of the host-side Java code
|
|
|
|
|
associated with these nanoapps can be found in the `java/` folder.
|