1*84e33947SAndroid Build Coastguard Worker# Design for Compatibility 2*84e33947SAndroid Build Coastguard Worker 3*84e33947SAndroid Build Coastguard Worker[TOC] 4*84e33947SAndroid Build Coastguard Worker 5*84e33947SAndroid Build Coastguard WorkerCompatibility is an important attribute of CHRE, which is accomplished through a 6*84e33947SAndroid Build Coastguard Workercombination of thoughtful API and framework design. When we refer to 7*84e33947SAndroid Build Coastguard Workercompatibility within the scope of CHRE, there are two main categories: 8*84e33947SAndroid Build Coastguard Worker 9*84e33947SAndroid Build Coastguard Worker* **Code compatibility**, which means that a nanoapp can be recompiled to run on 10*84e33947SAndroid Build Coastguard Worker a new platform without needing any code changes. CHRE provides this 11*84e33947SAndroid Build Coastguard Worker cross-device compatibility for all nanoapps which are written in a supported 12*84e33947SAndroid Build Coastguard Worker programming language (C11 or C++17), and reference only the standard CHRE APIs 13*84e33947SAndroid Build Coastguard Worker and mandatory standard library elements (or have these standard library 14*84e33947SAndroid Build Coastguard Worker functions statically linked into their binary). 15*84e33947SAndroid Build Coastguard Worker 16*84e33947SAndroid Build Coastguard Worker* **Binary compatibility**, which means that a nanoapp binary which has been 17*84e33947SAndroid Build Coastguard Worker compiled against a particular version of the CHRE API can run on a CHRE 18*84e33947SAndroid Build Coastguard Worker framework implementation which was compiled against a different version of the 19*84e33947SAndroid Build Coastguard Worker API. This is also called *cross-version compatibility*. Note that this does 20*84e33947SAndroid Build Coastguard Worker *not* mean that a nanoapp compiled against one version of the CHRE API can be 21*84e33947SAndroid Build Coastguard Worker compiled against a different version of the CHRE API without compiler errors - 22*84e33947SAndroid Build Coastguard Worker although rare, compile-time breakages are permitted with sufficient 23*84e33947SAndroid Build Coastguard Worker justification, since nanoapp developers can update their code at the time they 24*84e33947SAndroid Build Coastguard Worker migrate to the new API version. 25*84e33947SAndroid Build Coastguard Worker 26*84e33947SAndroid Build Coastguard WorkerThis section provides an overview of the mechanisms used to ensure 27*84e33947SAndroid Build Coastguard Workercompatibility. 28*84e33947SAndroid Build Coastguard Worker 29*84e33947SAndroid Build Coastguard Worker## CHRE API 30*84e33947SAndroid Build Coastguard Worker 31*84e33947SAndroid Build Coastguard WorkerThe CHRE API is a native C API that defines the interface between a nanoapp and 32*84e33947SAndroid Build Coastguard Workerany underlying CHRE implementation to provide cross-platform and cross-version 33*84e33947SAndroid Build Coastguard Workercompatibility. It is designed to be supportable even in very memory-constrained 34*84e33947SAndroid Build Coastguard Workerenvironments (total system memory in the hundreds of kilobytes range), and is 35*84e33947SAndroid Build Coastguard Workerthoroughly documented to clearly indicate the intended behavior. 36*84e33947SAndroid Build Coastguard Worker 37*84e33947SAndroid Build Coastguard WorkerThe CHRE API follows [semantic versioning](https://semver.org) principles to 38*84e33947SAndroid Build Coastguard Workermaintain binary compatibility. In short, this means that the minor version is 39*84e33947SAndroid Build Coastguard Workerincremented when new features and changes are introduced in a backwards 40*84e33947SAndroid Build Coastguard Workercompatible way, and the major version is only incremented on a 41*84e33947SAndroid Build Coastguard Workercompatibility-breaking change. One key design goal of the CHRE API is to avoid 42*84e33947SAndroid Build Coastguard Workermajor version changes if at all possible, through use of 43*84e33947SAndroid Build Coastguard Workercompatibility-preserving code in the framework and Nanoapp Support Library 44*84e33947SAndroid Build Coastguard Worker(NSL). 45*84e33947SAndroid Build Coastguard Worker 46*84e33947SAndroid Build Coastguard WorkerMinor version updates to the CHRE API typically occur alongside each Android 47*84e33947SAndroid Build Coastguard Workerrelease, but the CHRE version and Android version are not intrinsically related. 48*84e33947SAndroid Build Coastguard WorkerNanoapps should be compiled against the latest version to be able to use any 49*84e33947SAndroid Build Coastguard Workernewly added features, though nanoapp binaries are compatible across minor 50*84e33947SAndroid Build Coastguard Workerversion changes. 51*84e33947SAndroid Build Coastguard Worker 52*84e33947SAndroid Build Coastguard Worker### API Compatibility Design Principles 53*84e33947SAndroid Build Coastguard Worker 54*84e33947SAndroid Build Coastguard WorkerAPI design principles applied within CHRE to ensure compatibility include the 55*84e33947SAndroid Build Coastguard Workerfollowing (not an exhaustive list). These are recommended to be followed for any 56*84e33947SAndroid Build Coastguard Workervendor-specific API extensions as well. 57*84e33947SAndroid Build Coastguard Worker 58*84e33947SAndroid Build Coastguard Worker* Functionality must not be removed unless it was optional at the time of 59*84e33947SAndroid Build Coastguard Worker introduction, for example as indicated by a capabilities flag (an exception 60*84e33947SAndroid Build Coastguard Worker exists if it has no impact on the regular functionality of a nanoapp, for 61*84e33947SAndroid Build Coastguard Worker example a feature that only aids in debugging) 62*84e33947SAndroid Build Coastguard Worker* Reserved fields must be set to 0 by the sender and ignored by the recipient 63*84e33947SAndroid Build Coastguard Worker* Fields within a structure must not be reordered - new fields may only be 64*84e33947SAndroid Build Coastguard Worker introduced by reclaiming reserved fields (preferred), or adding to the end of 65*84e33947SAndroid Build Coastguard Worker a structure 66*84e33947SAndroid Build Coastguard Worker* When reclaiming a reserved field, the default value of 0 must indicate a 67*84e33947SAndroid Build Coastguard Worker property that is guaranteed to hold for previous API versions, or “unknown” 68*84e33947SAndroid Build Coastguard Worker* Arguments to a function must not be added or removed - introduce a new 69*84e33947SAndroid Build Coastguard Worker function instead 70*84e33947SAndroid Build Coastguard Worker* The meaning of constants (e.g. event types) must never be changed, but may be 71*84e33947SAndroid Build Coastguard Worker deprecated and eventually replaced 72*84e33947SAndroid Build Coastguard Worker 73*84e33947SAndroid Build Coastguard Worker## Binary Backward Compatibility and the NSL 74*84e33947SAndroid Build Coastguard Worker 75*84e33947SAndroid Build Coastguard WorkerThis is where we want a nanoapp compiled against e.g. v1.2 to run on a CHRE v1.1 76*84e33947SAndroid Build Coastguard Workeror older implementation. This is done through a combination of runtime feature 77*84e33947SAndroid Build Coastguard Workerdiscovery, and compatibility behaviors included in the Nanoapp Support Library 78*84e33947SAndroid Build Coastguard Worker(NSL). 79*84e33947SAndroid Build Coastguard Worker 80*84e33947SAndroid Build Coastguard WorkerRuntime feature discovery involves a nanoapp querying for the support of a 81*84e33947SAndroid Build Coastguard Workerfeature (e.g. RTT support indicated in `chreWifiGetCapabilities()`, or querying 82*84e33947SAndroid Build Coastguard Workerfor a specific sensor in `chreSensorFindDefault()`), which allows it determine 83*84e33947SAndroid Build Coastguard Workerwhether the associated functionality is expected to work. The nanoapp may also 84*84e33947SAndroid Build Coastguard Workerquery `chreGetApiVersion()` to find out the version of the CHRE API supported by 85*84e33947SAndroid Build Coastguard Workerthe platform it is running on. If a nanoapp has a hard requirement on some 86*84e33947SAndroid Build Coastguard Workermissing functionality, it may choose to return false from `nanoappStart()` to 87*84e33947SAndroid Build Coastguard Workerabort initialization. 88*84e33947SAndroid Build Coastguard Worker 89*84e33947SAndroid Build Coastguard WorkerHowever, a CHRE implementation cannot anticipate all future API changes and 90*84e33947SAndroid Build Coastguard Workerautomatically provide compatibility. So the NSL serves as a transparent shim 91*84e33947SAndroid Build Coastguard Workerwhich is compiled into the nanoapp binary to ensure this compatibility. For 92*84e33947SAndroid Build Coastguard Workerexample, a nanoapp compiled against v1.2 must be able to reference and call 93*84e33947SAndroid Build Coastguard Worker`chreConfigureHostSleepStateEvents()` when running on a CHRE v1.1 or earlier, 94*84e33947SAndroid Build Coastguard Workeralthough such a function call would have no effect in that case. Typical dynamic 95*84e33947SAndroid Build Coastguard Workerlinking approaches would find an unsatisfied dependency and fail to load the 96*84e33947SAndroid Build Coastguard Workernanoapp, even if it does not actually call the function, for example by wrapping 97*84e33947SAndroid Build Coastguard Workerit in a condition that first checks the CHRE version. In 98*84e33947SAndroid Build Coastguard Worker`platform/shared/nanoapp/nanoapp_support_lib_dso.cc`, this is supported by 99*84e33947SAndroid Build Coastguard Workerintercepting CHRE API function calls and either calling through to the 100*84e33947SAndroid Build Coastguard Workerunderlying platform if it’s supported, or replacing it with stub functionality. 101*84e33947SAndroid Build Coastguard Worker 102*84e33947SAndroid Build Coastguard WorkerAlong similar lines, if new fields are added to the end of a structure without 103*84e33947SAndroid Build Coastguard Workerrepurposing a reserved field in an update to the CHRE API, as was the case with 104*84e33947SAndroid Build Coastguard Worker`bearing_accuracy` in `chreGnssLocationEvent`, the nanoapp must be able to 105*84e33947SAndroid Build Coastguard Workerreference the new field without reading uninitialized memory. This is enabled by 106*84e33947SAndroid Build Coastguard Workerthe NSL, which can intercept the event, and copy it into the new, larger 107*84e33947SAndroid Build Coastguard Workerstructure, and set the new fields to their default values. 108*84e33947SAndroid Build Coastguard Worker 109*84e33947SAndroid Build Coastguard WorkerSince these NSL compatibility behaviors carry some amount of overhead (even if 110*84e33947SAndroid Build Coastguard Workervery slight), they can be disabled if it is known that a nanoapp will never run 111*84e33947SAndroid Build Coastguard Workeron an older CHRE version. This may be the case for a nanoapp developed for a 112*84e33947SAndroid Build Coastguard Workerspecific device, for example. The NSL may also limit its compatibility range 113*84e33947SAndroid Build Coastguard Workerbased on knowledge of the API version at which support for given hardware was 114*84e33947SAndroid Build Coastguard Workerintroduced. For example, if a new hardware family first added support for the 115*84e33947SAndroid Build Coastguard WorkerCHRE framework at API v1.1, then NSL support for v1.0 is unnecessary. 116*84e33947SAndroid Build Coastguard Worker 117*84e33947SAndroid Build Coastguard WorkerOutside of these cases, the NSL must provide backwards compatibility for at 118*84e33947SAndroid Build Coastguard Workerleast 3 previous versions, and is strongly recommended to provide support for 119*84e33947SAndroid Build Coastguard Workerall available versions. This means that if the first API supported by a target 120*84e33947SAndroid Build Coastguard Workerdevice is v1.0, then a nanoapp compiled against API v1.4 must have NSL support 121*84e33947SAndroid Build Coastguard Workerfor v1.1 through v1.4, and should ideally also support v1.0. 122*84e33947SAndroid Build Coastguard Worker 123*84e33947SAndroid Build Coastguard Worker## Binary Forward Compatibility and Framework Requirements 124*84e33947SAndroid Build Coastguard Worker 125*84e33947SAndroid Build Coastguard WorkerConversely, this is where we want a nanoapp compiled against e.g. v1.1 to run 126*84e33947SAndroid Build Coastguard Workeragainst CHRE v1.2 or later implementations. The NSL cannot directly provide this 127*84e33947SAndroid Build Coastguard Workerkind of compatibility, so it must be ensured through a combination of careful 128*84e33947SAndroid Build Coastguard WorkerCHRE API design, and compatibility behaviors in the CHRE framework. 129*84e33947SAndroid Build Coastguard Worker 130*84e33947SAndroid Build Coastguard WorkerSimilar to how Android apps have a “target SDK” attribute, nanoapps have a 131*84e33947SAndroid Build Coastguard Worker“target API version” which indicates the version of the CHRE API they were 132*84e33947SAndroid Build Coastguard Workercompiled against. The framework can inspect this value and provide compatibility 133*84e33947SAndroid Build Coastguard Workerbehavior as needed. For example, `chreGetSensorInfo()` populates memory provided 134*84e33947SAndroid Build Coastguard Workerby the nanoapp with information about a given sensor. In CHRE API v1.1, this 135*84e33947SAndroid Build Coastguard Workerstructure was extended with a new field, `minInterval`. Therefore, the framework 136*84e33947SAndroid Build Coastguard Workermust check if the nanoapp’s target API is v1.1 or later before writing this 137*84e33947SAndroid Build Coastguard Workerfield. 138*84e33947SAndroid Build Coastguard Worker 139*84e33947SAndroid Build Coastguard WorkerTo avoid carrying forward compatibility code indefinitely, it is permitted for a 140*84e33947SAndroid Build Coastguard WorkerCHRE implementation to reject compatibility with nanoapps compiled against an 141*84e33947SAndroid Build Coastguard WorkerAPI minor version that is 2 or more generations older. For example, a CHRE v1.4 142*84e33947SAndroid Build Coastguard Workerimplementation may reject attempts to load a nanoapp compiled against CHRE API 143*84e33947SAndroid Build Coastguard Workerv1.2, but it must ensure compatibility with v1.3. However, providing the full 144*84e33947SAndroid Build Coastguard Workerrange of compatibility generally does not require significant effort on behalf 145*84e33947SAndroid Build Coastguard Workerof the CHRE implementation, so this is recommended for maximum flexibility. 146*84e33947SAndroid Build Coastguard Worker 147*84e33947SAndroid Build Coastguard Worker## ABI Stability 148*84e33947SAndroid Build Coastguard Worker 149*84e33947SAndroid Build Coastguard WorkerCHRE does not define a standard Application Binary Interface (ABI) - this is 150*84e33947SAndroid Build Coastguard Workerleft as a platform responsibility in order to provide maximum flexibility. 151*84e33947SAndroid Build Coastguard WorkerHowever, CHRE implementations must ensure that binary compatibility is 152*84e33947SAndroid Build Coastguard Workermaintained with nanoapps, by choosing a design that provides this property. For 153*84e33947SAndroid Build Coastguard Workerexample, if a syscall-like approach is used (with the help of the NSL) to call 154*84e33947SAndroid Build Coastguard Workerfrom position-independent nanoapp code into fixed-position CHRE API functions 155*84e33947SAndroid Build Coastguard Worker(e.g. in a statically linked monolithic firmware image), syscall IDs and their 156*84e33947SAndroid Build Coastguard Workercalling conventions must remain stable. It is not acceptable to require all 157*84e33947SAndroid Build Coastguard Workernanoapps to be recompiled to be able to work with an updated CHRE 158*84e33947SAndroid Build Coastguard Workerimplementation. 159*84e33947SAndroid Build Coastguard Worker 160*84e33947SAndroid Build Coastguard Worker## CHRE PALs 161*84e33947SAndroid Build Coastguard Worker 162*84e33947SAndroid Build Coastguard WorkerSince the PAL APIs are largely based on the CHRE APIs, they benefit from many of 163*84e33947SAndroid Build Coastguard Workerthe compatibility efforts by default. Overall, binary compatibility in the CHRE 164*84e33947SAndroid Build Coastguard WorkerPAL APIs are less involved than the CHRE APIs, because we expect CHRE and CHRE 165*84e33947SAndroid Build Coastguard WorkerPAL implementations to be built into the vendor image together, and usually run 166*84e33947SAndroid Build Coastguard Workerat the same version except for limited periods during development. However, a 167*84e33947SAndroid Build Coastguard WorkerPAL implementation can simultaneously support multiple PAL API versions from a 168*84e33947SAndroid Build Coastguard Workersingle codebase by adapting its behavior based on the `requestedApiVersion` 169*84e33947SAndroid Build Coastguard Workerparameter in the \*GetApi method, e.g. `chrePalWifiGetApi()`. 170*84e33947SAndroid Build Coastguard Worker 171*84e33947SAndroid Build Coastguard Worker## Deprecation Strategy 172*84e33947SAndroid Build Coastguard Worker 173*84e33947SAndroid Build Coastguard WorkerIn general, nanoapp compilation may be broken in a minor update (given 174*84e33947SAndroid Build Coastguard Workersufficient justification - this is not a light decision to make, considering the 175*84e33947SAndroid Build Coastguard Workerdownstream impact to nanoapp developers), but deprecation of functionality at a 176*84e33947SAndroid Build Coastguard Workerbinary level occurs over a minimum of 2 years (minor versions). The general 177*84e33947SAndroid Build Coastguard Workerprocess for deprecating a function in the CHRE API is as follows: 178*84e33947SAndroid Build Coastguard Worker 179*84e33947SAndroid Build Coastguard Worker* In a new minor version `N` of the CHRE API, the function is marked with 180*84e33947SAndroid Build Coastguard Worker `@deprecated`, with a description of the recommended alternative, and ideally 181*84e33947SAndroid Build Coastguard Worker the justification for the deprecation, so nanoapp developers know why it's 182*84e33947SAndroid Build Coastguard Worker important to update. 183*84e33947SAndroid Build Coastguard Worker 184*84e33947SAndroid Build Coastguard Worker * Depending on the severity of impact, the function may also be tagged with a 185*84e33947SAndroid Build Coastguard Worker compiler attribute to generate a warning (e.g. `CHRE_DEPRECATED`) that may 186*84e33947SAndroid Build Coastguard Worker be ignored. Or, version `N` or later, an attribute or other method may be 187*84e33947SAndroid Build Coastguard Worker used to break compilation of nanoapps using the deprecated function, forcing 188*84e33947SAndroid Build Coastguard Worker them to update. If not considered a high severity issue and compatibility is 189*84e33947SAndroid Build Coastguard Worker easy to maintain, it is recommended to break compilation only in version 190*84e33947SAndroid Build Coastguard Worker `N+2` or later. 191*84e33947SAndroid Build Coastguard Worker 192*84e33947SAndroid Build Coastguard Worker * Binary compatibility at this stage must be maintained. For example the NSL 193*84e33947SAndroid Build Coastguard Worker should map the new functionality to the deprecated function when running on 194*84e33947SAndroid Build Coastguard Worker CHRE `N-1` or older, or a suitable alternative must be devised. Likewise, 195*84e33947SAndroid Build Coastguard Worker CHRE must continue to provide the deprecated function to support nanoapps 196*84e33947SAndroid Build Coastguard Worker built against `N-1`. 197*84e33947SAndroid Build Coastguard Worker 198*84e33947SAndroid Build Coastguard Worker* Impacts to binary compatibility on the CHRE side may occur 2 versions after 199*84e33947SAndroid Build Coastguard Worker the function is made compilation-breaking for nanoapps, since forward 200*84e33947SAndroid Build Coastguard Worker compatibility is guaranteed for 2 minor versions. If done, the nanoapp must be 201*84e33947SAndroid Build Coastguard Worker rejected at load time. 202*84e33947SAndroid Build Coastguard Worker 203*84e33947SAndroid Build Coastguard Worker* Impacts to binary compatibility on the nanoapp side may occur 4 versions after 204*84e33947SAndroid Build Coastguard Worker the function is marked deprecated (at `N+4`), since backward compatibility is 205*84e33947SAndroid Build Coastguard Worker guaranteed for 4 minor versions. If done, the NSL must cause `nanoappStart()` 206*84e33947SAndroid Build Coastguard Worker to return false on version `N` or older. 207*84e33947SAndroid Build Coastguard Worker 208*84e33947SAndroid Build Coastguard WorkerFor example, if a function is marked deprecated in `N`, and becomes a 209*84e33947SAndroid Build Coastguard Workercompilation-breaking error in `N+2`, then a CHRE implementation at `N+4` may 210*84e33947SAndroid Build Coastguard Workerremove the deprecated functionality only if it rejects a nanoapp built against 211*84e33947SAndroid Build Coastguard Worker`N+1` or older at load time. Likewise, the NSL can remove compatibility code for 212*84e33947SAndroid Build Coastguard Workerthe deprecated function at `N+4`. CHRE and NSL implementations must not break 213*84e33947SAndroid Build Coastguard Workercompatibility in a fragmented, unpredictable, or hidden way, for example by 214*84e33947SAndroid Build Coastguard Workerreplacing the deprecated function with a stub that does nothing. If it is 215*84e33947SAndroid Build Coastguard Workerpossible for CHRE and/or the NSL to detect only nanoapps that use the deprecated 216*84e33947SAndroid Build Coastguard Workerfunctionality, then it is permissible to block loading of only those nanoapps, 217*84e33947SAndroid Build Coastguard Workerbut otherwise this must be a blanket ban of all nanoapps compiled against the 218*84e33947SAndroid Build Coastguard Workerold API version. 219