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