1# CHRE Framework Porting Guide 2 3[TOC] 4 5CHRE achieves portability and extensibility across platforms by defining 6interfaces that the platform needs to implement. These interfaces provide 7dependencies for the common CHRE code that are necessarily platform-specific. 8Additionally, platform code calls into common code to ferry events from 9underlying subsystems to nanoapps. 10 11This section gives an overview of the steps one should take to add support for a 12new platform in the CHRE reference implementation. 13 14## Directory Structure 15 16CHRE platform code can be broadly categorized as follows. 17 18### Platform Interfaces 19 20Files under `platform/include` serve as the interface between common code in 21`core/` and other platform-specific code in `platform/<platform_name>`. These 22files are considered common and should not be modified for the sake of 23supporting an individual platform. 24 25### Shared Platform Code 26 27Located in `platform/shared/`, the code here is part of the platform layer’s 28responsibilities, but is not necessarily specific to only one platform. In other 29words, this code is likely to be re-used by multiple platforms, but it is not 30strictly necessary for a given platform to use it. 31 32### Platform-specific Code 33 34Files under `platform/<platform_name>` are specific to the underlying software 35of a given platform, for example the APIs which are used to access functionality 36like sensors, the operating system, etc. To permit code reuse, the CHRE platform 37layer for a given device may be composed of files from multiple 38`<platform_name>` folders, for example if the same sensor framework is supported 39across multiple OSes, there may be one folder that provides the components that 40are specific to just the OS. 41 42Platform-specific code can be further subdivided into: 43 44* **Source files**: normally included at 45 `platform/<platform_name>/<file_name>.cc`, but may appear in a subdirectory 46 47* **Headers which are includable by common code**: these are placed at 48 `platform/<platform_name>/include/chre/target_platform/<file_name>.h`, and are 49 included by *Platform Interfaces* found in `platform/include` and provide 50 inline or base class definitions, such as `mutex_base_impl.h` and 51 `platform_sensor_base.h` respectively, or required macros 52 53* **Fully platform-specific headers**: these typically appear at 54 `platform/<platform_name>/include/chre/platform/<platform_name/<file_name>.h` 55 and may only be included by other platform-specific code 56 57## Open Sourcing 58 59Partners who add support for a new platform are recommended to upstream their 60code to 61[AOSP](https://source.android.com/setup/contribute#contribute-to-the-code). 62This helps ensure that details of your platform are considered by the team that 63maintains the core framework, so any changes that break compilation are 64addressed in a timely fashion, and enables you to receive useful code review 65feedback to improve the quality of your CHRE implementation. Please reach out 66via your TAM to help organize this effort. 67 68If some parts of a platform’s CHRE implementation must be kept closed source, 69then it is recommended to be kept in a separate Git project (under vendor/ in 70the Android tree). This vendor-private code can be integrated with the main CHRE 71build system through the `CHRE_VARIANT_MK_INCLUDES` variable. See the build 72system documentation for more details. 73 74## Recommended Steps for Porting CHRE 75 76When starting to add support for a new platform in the CHRE framework, it’s 77recommended to break the task into manageable chunks, to progressively add more 78functionality until the full desired feature set is achieved. An existing 79platform implementation can be referenced to create empty stubs, and then 80proceed to add implementations piece by piece, testing along the way. 81 82CHRE provides various test nanoapps in `apps/` that exercise a particular 83feature that the platform provides. These are selectively compiled into the 84firmware statically via a `static_nanoapps.cc` source file. 85 86With this in mind, it is recommended to follow this general approach: 87 881. Create a new platform with only empty stubs, with optional features (like 89 `CHRE_GNSS_SUPPORT_ENABLED`) disabled at build-time 90 912. Work on updating the build system to add a new build target and achieve 92 successful compilation and linking (see the build system documentation for 93 details) 94 953. Implement base primitives from `platform/include`, including support for 96 mutexes, condition variables, atomics, time, timers, memory allocation, and 97 logging 98 994. Add initialization code to start the CHRE thread 100 1015. Add static nanoapp initialization support (usually this is just a copy/paste 102 from another platform) 103 1046. Confirm that the ‘hello world’ nanoapp produces the expected log message (if 105 it does, huzzah!) 106 1077. Complete any remaining primitives, like assert 108 1098. Implement host link and the daemon/HAL on the host (AP) side, and validate it 110 with a combination of the message world nanoapp and the host-side test code 111 found at `host/common/test/chre_test_client.cc` 112 113At this stage, the core functionality has been enabled, and further steps should 114include enabling dynamic loading (described in its own section below), and the 115desired optional feature areas, like sensors (potentially via their respective 116PALs, described in the next section). 117 118## Implementing the Context Hub HAL 119 120The Context Hub HAL (found in the Android tree under 121`hardware/interfaces/contexthub`) defines the interface between Android and the 122underlying CHRE implementation, but as CHRE is implemented on a different 123processor from the HAL, the HAL is mostly responsible for relaying messages to 124CHRE. This project includes an implementation of the Context Hub HAL under 125`host/hal_generic` which pairs with the CHRE framework reference implementation. 126It converts between HAL API calls and serialized flatbuffers messages, using the 127host messaging protocol defined under `platform/shared` (platform 128implementations are able to choose a different protocol if desired, but would 129require a new HAL implementation), and passes the messages to and from the CHRE 130daemon over a socket. The CHRE daemon is in turn responsible for communicating 131directly with CHRE, including common functionality like relaying messages to and 132from nanoapps, as well as device-specific functionality as needed. Some examples 133of CHRE functionality that are typically implemented with support from the CHRE 134daemon include: 135 136* Loading preloaded nanoapps at startup 137* Passing log messages from CHRE into Android logcat 138* Determining the offset between `chreGetTime()` and Android’s 139 `SystemClock.elapsedRealtimeNanos()` for use with 140 `chreGetEstimatedHostTimeOffset()` 141* Coordination with the SoundTrigger HAL for audio functionality 142* Exposing CHRE functionality to other vendor-specific components (e.g. via 143 `chre::SocketClient`) 144 145When adding support for a new platform, a new HAL implementation and/or daemon 146implementation on the host side may be required. Refer to code in the `host/` 147directory for examples. 148 149## Implementing Optional Feature Areas (e.g. PALs) 150 151CHRE provides groups of functionality called *feature areas* which are 152considered optional from the perspective of the CHRE API, but may be required to 153support a desired nanoapp. CHRE feature areas include sensors, GNSS, audio, and 154others. There are two ways by which this functionality can be exposed to the 155common CHRE framework code: via the `Platform<Module>` C++ classes, or the C PAL 156(Platform Abstraction Layer) APIs. It may not be necessary to implement all of 157the available feature areas, and they can instead be disabled if they won’t be 158implemented. 159 160The Platform C++ Classes and PAL APIs have extensive documentation in their 161header files, including details on requirements. Please refer to the headers for 162precise implementation details. 163 164### Platform C++ Classes vs. PAL APIs 165 166Each feature area includes one or more `Platform<Module>` classes which the 167common framework code directly interacts with. These classes may be directly 168implemented to provide the given functionality, or the shim to the PAL APIs 169included in the `shared` platform directory may be used. PALs provide a C API 170which is suitable for use as a binary interface, for example between two dynamic 171modules/libraries, and it also allows for the main CHRE to platform-specific 172translation to be implemented in C, which may be preferable in some cases. 173 174Note that the PAL APIs are binary-stable, in that it’s possible for the CHRE 175framework to work with a module that implements a different minor version of the 176PAL API, full backwards compatibility (newer CHRE framework to older PAL) is not 177guaranteed, and may not be possible due to behavioral changes in the CHRE API. 178While it is possible for a PAL implementation to simultaneously support multiple 179versions of the PAL API, it is generally recommended to ensure the PAL API 180version matches between the framework and PAL module, unless the source control 181benefits of a common PAL binary are desired. 182 183This level of compatibility is not provided for the C++ `Platform<Module>` 184classes, as the CHRE framework may introduce changes that break compilation. If 185a platform implementation is included in AOSP, then it is possible for the 186potential impact to be evaluated and addressed early. 187 188### Disabling Feature Areas 189 190If a feature area is not supported, setting the make variable 191`CHRE_<name>_SUPPORT_ENABLED` to false in the variant makefile will avoid 192inclusion of common code for that feature area. Note that it must still be 193possible for the associated CHRE APIs to be called by nanoapps without crashing 194- these functions must return an appropriate response indicating the lack of 195 support (refer to `platform/shared/chre_api_<name>.cc` for examples). 196 197### Implementing Platform C++ Classes 198 199As described in the CHRE Framework Overview section, CHRE abstracts common code 200from platform-specific code at compile time by inheriting through 201`Platform<Module>` and `Platform<Module>Base` classes. Platform-specific code 202may retrieve a reference to other objects in CHRE via 203`EventLoopManagerSingleton::get()`, which returns a pointer to the 204`EventLoopManager` object which contains all core system state. Refer to the 205`Platform<Module>` header file found in `platform/include`, and implementation 206examples from other platforms for further details. 207 208### Implementing PALs 209 210PAL implementations must only use the callback and system APIs provided in 211`open()` to call into the CHRE framework, as the other functions in the CHRE 212framework do not have a stable API. 213 214If a PAL implementation is provided as a dynamic module in binary form, it can 215be linked into the CHRE framework at build time by adding it to 216`TARGET_SO_LATE_LIBS` in the build variant’s makefile - see the build system 217documentation for more details. 218 219### PAL Verification 220 221There are several ways to test the PAL implementation beyond manual testing. 222Some of them are listed below in increasing order of the amount of checks run by 223the tests. 224 2251. Use the FeatureWorld apps provided under the `apps` directory to exercise 226the various PAL APIs and verify the CHRE API requirements are being met 227 2282. Assuming the platform PAL implementations utilize CHPP and can communicate 229from the host machine to the target chipset, execute `run_pal_impl_tests.sh` to 230run basic consistency checks on the PAL 231 2323. Execute tests (see Testing section for details) 233 234## Dynamic Loading Support 235 236CHRE requires support for runtime loading and unloading of nanoapp binaries. 237There are several advantages to this approach: 238 239* Decouples nanoapp binaries from the underlying system - can maintain and 240 deploy a single nanoapp binary across multiple devices, even if they support 241 different versions of Android or the CHRE API 242 243* Makes it possible to update nanoapps without requiring a system reboot, 244 particularly on platforms where CHRE runs as part of a statically compiled 245 firmware 246 247* Enables advanced capabilities, like staged rollouts and targeted A/B testing 248 249While dynamic loading is a responsibility of the platform implementation and may 250already be a part of the underlying OS/system capabilities, the CHRE team is 251working on a reference implementation for a future release. Please reach out via 252your TAM if you are interested in integrating this reference code prior to its 253public release. 254