xref: /aosp_15_r20/system/chre/doc/compatibility.md (revision 84e339476a462649f82315436d70fd732297a399)
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