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### Build Customization 60 61As part of the CHRE framework build system, the `CHRE_VARIANT_MK_INCLUDES` 62environment variable can be used to inject an external `.mk` file into the 63top-level build without any source code changes in the system/chre project. 64Alternatively, if open sourcing, the `platform.mk` file should contain the 65additions needed to support the new vendor API. Refer to the CHRE framework 66build documentation for further details. 67 68To expose the new functionality to nanoapps, it’s recommended to create a single 69`.mk` file that adds the necessary `COMMON_CFLAGS` entries (and potentially 70other build configuration). For example, create a `chrexyz.mk` file which 71nanoapps should include in their Makefile prior to including 72`$(CHRE_PREFIX)/build/nanoapp/app.mk`. 73 74## Threading Model 75 76Interactions with a nanoapp always happen from within the CHRE thread that runs 77the EventLoop, so vendor extension code does not need to worry about race 78conditions due to multiple nanoapps calling into APIs, and likewise nanoapps do 79not need to worry about race conditions in its callbacks/handlers. However, it 80is common for a platform module to receive data in a callback on another thread. 81In that case, it is recommended to use `EventLoopManager::deferCallback()` to 82pass the incoming data to the CHRE thread for processing, as opposed to using 83mutexes or other synchronization primitives, to avoid multithreading-related 84issues that can arise in rare conditions. Further, note that most of the core 85CHRE functionality is only safe to call from within the CHRE thread (other than 86posting an event, or methods that are explicitly marked as thread-safe). 87 88## Initialization 89 90Since the new API will not be part of the core framework, it won’t be attached 91to `EventLoopManager` or initialized as part of `chre::init()` or 92`EventLoopManagerSingleton::get()->lateInit()`, since vendor-extension APIs are 93by definition not part of the common code. Instead, a separate singleton object 94should be created, for example `chre::xyz::VendorExtensionManager`, and 95platform-specific initialization code should invoke any necessary initialization 96**after** `chre::init` is called, but **before** loading any static nanoapps or 97invoking `EventLoop::run()` to ensure that nanoapps don’t begin interacting with 98the API before its state is ready. 99 100## Handling Nanoapp API Calls 101 102Calls from a nanoapp into the CHRE framework first arrive in platform-specific 103code (refer to the Framework Overview documentation for details). The first step 104once an API call reaches the framework is usually to call 105`EventLoopManager::validateChreApiCall(__func__)`. This fetches a pointer to the 106`Nanoapp` object associated with the nanoapp that invoked the API, which will 107fail if the API is called outside of the EventLoop thread context (see the 108Threading Model above). From this point, the vendor extension singleton should 109be used to invoke the appropriate functionality. 110 111## Sending Events to Nanoapps 112 113Vendor extension APIs that need to pass data to a nanoapp asynchronously should 114use the event susbsystem, using the vendor-reserved event type range (starting 115at `CHRE_EVENT_INTERNAL_EXTENDED_FIRST_EVENT` and extending to 116`CHRE_EVENT_INTERNAL_LAST_EVENT`). Event types for a given vendor extension 117should be globally unique and stable over time. 118 119Synchronous API calls that can potentially block for periods greater than a few 120milliseconds are discouraged, as these can prevent other nanoapps from 121executing, and/or cause the pending event queue to grow excessively during 122periods of high activity. Refer to the GNSS and WWAN APIs for design patterns 123related to passing data to a nanoapp asynchronously, using custom event payloads 124and/or `chreAsyncResult`. 125 126Events can either be unicast to a nanoapp identified by its instance ID 127(`Nanoapp::getInstanceId()`), or broadcast to all nanoapps registered for the 128given event type - see `Nanoapp::registerForBroadcastEvent()` and 129`Nanoapp::unregisterForBroadcastEvent()`. 130 131Use `EventLoop::postEventOrDie()` or `EventLoop::postLowPriorityEventOrFree()` 132(via `EventLoopManagerSingleton::get()->getEventLoop()`) to pass events to 133nanoapps, depending on what error handling is desired in the case that the event 134cannot be posted to the queue. Any memory referenced by `eventData` must not be 135modified until `freeCallback` is invoked. 136