• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Extending CHRE with Vendor-specific Functionality
2
3[TOC]
4
5The CHRE framework is easily extensible with no modifications to the core
6framework. Depending on the goals of the new API, one or more of the following
7steps must be performed. At a high-level, to add a new vendor-specific API to
8CHRE, one must:
9
101. Define new APIs in a header that can be referenced by both platform CHRE
11   framework code and vendor-specific nanoapps.
12
132. Expose the new APIs from the framework to nanoapps, and connect them to a new
14   module to provide the desired functionality
15
163. Integrate the new module with existing CHRE framework features, e.g. the
17   event subsystem, to provide complete functionality that fits within the
18   existing CHRE conventions
19
20It's best to refer to existing standard CHRE API feature areas, such as
21`chre/wifi.h` and `WifiRequestManager`, and follow a similar design where
22possible.
23
24## Defining the API
25
26To prevent collision with future common CHRE API definitions, vendor extensions
27must not use the plain ‘chre’ prefix followed by a capitalized letter. Instead,
28it’s recommended to prefix the APIs with the vendor’s name as lowercase. For
29example, if your company name is XYZ Semiconductor and you’re defining a new
30‘widget’ API, it’s recommended to use a naming scheme like
31`chrexyzWidget<FunctionName>()`, and included indirectly via `#include
32<chre_xyz.h>` or directly via `<chre_xyz/widget.h>`. The equivalent C++
33namespace would be `::chre::xyz`.
34
35There are reserved ranges for vendor/implementation-specific event types
36(starting from `CHRE_EVENT_INTERNAL_EXTENDED_FIRST_EVENT`), and other cases
37where vendors may wish or need to define a custom value in an existing field. To
38prevent collision with future versions of the CHRE API, vendor extensions must
39only use values within vendor-reserved ranges. If you would like to add a new
40value to an existing field for a vendor extension and a vendor-reserved range
41does not already exist, please reach out to the CHRE team for guidance -
42solutions may involve creating a new reserved range in the common CHRE API, or
43providing advice on a different method of defining the API.
44
45Vendors can only add on to the CHRE API - existing APIs must not be changed. Do
46not modify core CHRE definitions, for example by adding on fields to common
47structures, re-using event types, repurposing fields that are reserved for
48future use, etc.
49
50It’s recommended that any vendor extensions consider compatibility when
51designing it - see the Compatibility section for API design guidelines.
52
53If this API is intended to be open-sourced, it should be added to
54`platform/<platform_name>/extensions/include`. Otherwise, it’s suggested that
55the API be placed outside of the CHRE tree, in a separate Git project under
56`vendor/` in the Android tree, to avoid potential conflicts when upgrading to a
57new version of CHRE.
58
59## Vendor sensor types
60
61CHRE has reserved a range of types for vendors to define their own sensor types.
62The starting point is `CHRE_SENSOR_TYPE_VENDOR_START`. For example, a vendor can
63define their own type as:
64
65```
66#define CHREX_SENSOR_TYPE_NEUTRINO_DETECTOR (CHRE_SENSOR_TYPE_VENDOR_START + X)
67```
68
69In `platform/shared/sensor_pal/platform_sensor_type_helpers.cc` macro
70`CHREX_SENSOR_SUPPORT` is used to select whether vendor sensor types are
71supported or not. Such macro can be defined in the `variant.mk`, e.g.,
72`variant/tinysys/variant.mk` for tinysys, to selectively pull in source files
73from vendor specific projects during compilation.
74
75### Build Customization
76
77As part of the CHRE framework build system, the `CHRE_VARIANT_MK_INCLUDES`
78environment variable can be used to inject an external `.mk` file into the
79top-level build without any source code changes in the system/chre project.
80Alternatively, if open sourcing, the `platform.mk` file should contain the
81additions needed to support the new vendor API. Refer to the CHRE framework
82build documentation for further details.
83
84To expose the new functionality to nanoapps, it’s recommended to create a single
85`.mk` file that adds the necessary `COMMON_CFLAGS` entries (and potentially
86other build configuration). For example, create a `chrexyz.mk` file which
87nanoapps should include in their Makefile prior to including
88`$(CHRE_PREFIX)/build/nanoapp/app.mk`.
89
90## Threading Model
91
92Interactions with a nanoapp always happen from within the CHRE thread that runs
93the EventLoop, so vendor extension code does not need to worry about race
94conditions due to multiple nanoapps calling into APIs, and likewise nanoapps do
95not need to worry about race conditions in its callbacks/handlers. However, it
96is common for a platform module to receive data in a callback on another thread.
97In that case, it is recommended to use `EventLoopManager::deferCallback()` to
98pass the incoming data to the CHRE thread for processing, as opposed to using
99mutexes or other synchronization primitives, to avoid multithreading-related
100issues that can arise in rare conditions. Further, note that most of the core
101CHRE functionality is only safe to call from within the CHRE thread (other than
102posting an event, or methods that are explicitly marked as thread-safe).
103
104## Initialization
105
106Since the new API will not be part of the core framework, it won’t be attached
107to `EventLoopManager` or initialized as part of `chre::init()` or
108`EventLoopManagerSingleton::get()->lateInit()`, since vendor-extension APIs are
109by definition not part of the common code. Instead, a separate singleton object
110should be created, for example `chre::xyz::VendorExtensionManager`, and
111platform-specific initialization code should invoke any necessary initialization
112**after** `chre::init` is called, but **before** loading any static nanoapps or
113invoking `EventLoop::run()` to ensure that nanoapps don’t begin interacting with
114the API before its state is ready.
115
116## Handling Nanoapp API Calls
117
118Calls from a nanoapp into the CHRE framework first arrive in platform-specific
119code (refer to the Framework Overview documentation for details). The first step
120once an API call reaches the framework is usually to call
121`EventLoopManager::validateChreApiCall(__func__)`. This fetches a pointer to the
122`Nanoapp` object associated with the nanoapp that invoked the API, which will
123fail if the API is called outside of the EventLoop thread context (see the
124Threading Model above). From this point, the vendor extension singleton should
125be used to invoke the appropriate functionality.
126
127## Sending Events to Nanoapps
128
129Vendor extension APIs that need to pass data to a nanoapp asynchronously should
130use the event susbsystem, using the vendor-reserved event type range (starting
131at `CHRE_EVENT_INTERNAL_EXTENDED_FIRST_EVENT` and extending to
132`CHRE_EVENT_INTERNAL_LAST_EVENT`). Event types for a given vendor extension
133should be globally unique and stable over time.
134
135Synchronous API calls that can potentially block for periods greater than a few
136milliseconds are discouraged, as these can prevent other nanoapps from
137executing, and/or cause the pending event queue to grow excessively during
138periods of high activity. Refer to the GNSS and WWAN APIs for design patterns
139related to passing data to a nanoapp asynchronously, using custom event payloads
140and/or `chreAsyncResult`.
141
142Events can either be unicast to a nanoapp identified by its instance ID
143(`Nanoapp::getInstanceId()`), or broadcast to all nanoapps registered for the
144given event type - see `Nanoapp::registerForBroadcastEvent()` and
145`Nanoapp::unregisterForBroadcastEvent()`.
146
147Use `EventLoop::postEventOrDie()` or `EventLoop::postLowPriorityEventOrFree()`
148(via `EventLoopManagerSingleton::get()->getEventLoop()`) to pass events to
149nanoapps, depending on what error handling is desired in the case that the event
150cannot be posted to the queue. Any memory referenced by `eventData` must not be
151modified until `freeCallback` is invoked.
152