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#### Recommended Implementation flow
220
221While there may be minor differences, most CHRE PAL [API][CHRE_PAL_DIR_URL]
222implementations follow the following pattern:
223
2241. **Implement the Module API for CHRE**
225
226CHRE provides a standardized structure containing various interfaces for
227calling into the vendor's closed source code in _pal/<feature>.h_. These
228functions must be implemented by the platform, and provided to CHRE when a call
229to _chrePal<feature>GetApi_ function is called. Functions to be implemented are
230of two broad categories:
231
232* _Access functions_
233
234      CHRE provides feature specific callbacks (see 2. below) to the PAL by
235      invoking the _open()_ function in the Module API provided above. The
236      structures returned by this function call must be stored somewhere by the
237      PAL, and used as necessary to call into the CHRE core. Typically, one or
238      more of these callbacks need to be invoked in response to a request from
239      CHRE using the Module API provided above.
240
241      The _close()_ function, when invoked by CHRE, indicates that CHRE is
242      shutting down. It is now the PAL's responsibility to perform cleanup,
243      cancel active requests, and not invoke any CHRE callbacks from this point
244      on.
245
246* _Request functions_
247
248      These are interfaces in the PAL API that are module specific, and used by
249      CHRE to call into the vendor PAL code.
250
2512. ** Use CHRE's callbacks **
252
253CHRE provides a set of module specific callbacks by invoking the _open()_ access
254function provided by the Module API. It then starts performing control or data
255requests as needed, by invoking the request functions in the Module API. The PAL
256is expected to process these requests, and invoke the appropriate CHRE provided
257callback in response. Note that some callbacks might require memory ownership
258to be held until explicitly released. For example, upon an audio request from
259CHRE via a call to the `requestAudioDataEvent` audio PAL API, the platform
260might invoke the `audioDataEventCallback` when the audio data is ready and
261packaged approapriately into a `chreAudioDataEvent` structure. The platform
262must ensure that the memory associated with this data structure remains in
263context until CHRE explicitly releases it via a call to `releaseAudioDataEvent`.
264
265Please refer to the appropriate PAL documentation to ensure that such
266dependencies are understood early in the development phase.
267
268#### Reference implementations
269
270Please refer to the various reference implementations that are
271[available][CHRE_LINUX_DIR_URL] for CHRE PALS for the Linux platform. Note that
272this implementation is meant to highlight the usage of the PAL APIs and
273callbacks, and might not necessarily port directly over into a resource
274constrained embedded context.
275
276### PAL Verification
277
278There are several ways to test the PAL implementation beyond manual testing.
279Some of them are listed below in increasing order of the amount of checks run by
280the tests.
281
2821.  Use the FeatureWorld apps provided under the `apps` directory to exercise
283the various PAL APIs and verify the CHRE API requirements are being met
284
2852. Assuming the platform PAL implementations utilize CHPP and can communicate
286from the host machine to the target chipset, execute `run_pal_impl_tests.sh` to
287run basic consistency checks on the PAL
288
2893.  Execute tests (see Testing section for details)
290
291## Dynamic Loading Support
292
293CHRE requires support for runtime loading and unloading of nanoapp binaries.
294There are several advantages to this approach:
295
296* Decouples nanoapp binaries from the underlying system - can maintain and
297  deploy a single nanoapp binary across multiple devices, even if they support
298  different versions of Android or the CHRE API
299
300* Makes it possible to update nanoapps without requiring a system reboot,
301  particularly on platforms where CHRE runs as part of a statically compiled
302  firmware
303
304* Enables advanced capabilities, like staged rollouts and targeted A/B testing
305
306While dynamic loading is a responsibility of the platform implementation and may
307already be a part of the underlying OS/system capabilities, the CHRE team is
308working on a reference implementation for a future release. Please reach out via
309your TAM if you are interested in integrating this reference code prior to its
310public release.
311
312[CHRE_PAL_DIR_URL]:  https://cs.android.com/android/platform/superproject/+/master:system/chre/pal/include/chre/pal/
313[CHRE_LINUX_DIR_URL]: https://cs.android.com/android/platform/superproject/+/master:system/chre/platform/linux/
314
315## Adding Context Hub support
316
317Once you have implemented the necessary pieces described previously, you are
318now ready to add the Context Hub support on the device! Here are the necessary
319steps to do this:
320
3211. Add the HAL implementation on the device
322
323Add the build target of the Context Hub HAL implementation to your device .mk
324file. For example, if the default generic Context Hub HAL is being used, you
325can add the following:
326
327```
328PRODUCT_PACKAGES += \
329    android.hardware.contexthub-service.generic
330```
331
332
333Currently, the generic Context Hub HAL relies on the CHRE daemon to communicate
334with CHRE. If you are using one of our existing platforms, you can add one of
335the following CHRE daemon build targets to your PRODUCT_PACKAGES as you did the
336generic HAL above.
337
338Qualcomm target: `chre`\
339Exynos target: `chre_daemon_exynos`\
340MediaTek target: `TBD`
341
342Otherwise, you can look at those target definitions to define a new one for
343your specific platform.
344
3452. Add the relevant SElinux policies for the device
346
347Resolve any missing SElinux violations by using the relevant tools such as
348audit2allow, and updating the SElinux policies for your device. You may follow
349the directions in [the official Android page](https://source.android.com/docs/security/features/selinux/validate)
350for additional guidance.
351
3523. Add the Context Hub feature flag for the device
353
354Add the following in your device.mk file:
355
356```
357PRODUCT_COPY_FILES += \
358    frameworks/native/data/etc/android.hardware.context_hub.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.context_hub.xml
359```
360
361The above change will enable the Context Hub Service on the device, and expects
362that the Context Hub HAL comes up. If (1) and (2) are not performed, the device
363may fail to boot to the Android home screen.
364