1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Note that to avoid always polluting the include paths of nanoapps, we use
18 // symlinks under the chre_nsl_internal include path to the "real" files, e.g.
19 // chre_nsl_internal/platform/shared maps to the same files that would normally
20 // be included via chre/platform/shared
21 
22 #include "chre_nsl_internal/platform/shared/nanoapp_support_lib_dso.h"
23 
24 #include <algorithm>
25 
26 #include "chre_api/chre.h"
27 #include "chre_nsl_internal/platform/shared/debug_dump.h"
28 #include "chre_nsl_internal/util/macros.h"
29 #include "chre_nsl_internal/util/system/napp_permissions.h"
30 #ifdef CHRE_NANOAPP_USES_WIFI
31 #include "chre_nsl_internal/util/system/wifi_util.h"
32 #endif
33 
34 #ifndef LOG_TAG
35 #define LOG_TAG "[NSL]"
36 #endif  // LOG_TAG
37 
38 /**
39  * @file
40  * The Nanoapp Support Library (NSL) that gets built with nanoapps to act as an
41  * intermediary to the reference CHRE implementation. It provides hooks so the
42  * app can be registered with the system, and also provides a layer where we can
43  * implement cross-version compatibility features as needed.
44  */
45 
46 namespace {
47 
48 constexpr uint32_t kNanoappPermissions = 0
49 // DO NOT USE this macro outside of specific CHQTS nanoapps. This is only used
50 // to allow testing of invalid permission declarations.
51 #ifdef CHRE_TEST_NANOAPP_PERMS
52                                          | CHRE_TEST_NANOAPP_PERMS
53 #else
54 #ifdef CHRE_NANOAPP_USES_AUDIO
55     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_AUDIO)
56 #endif
57 #ifdef CHRE_NANOAPP_USES_BLE
58     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_BLE)
59 #endif
60 #ifdef CHRE_NANOAPP_USES_GNSS
61     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_GNSS)
62 #endif
63 #ifdef CHRE_NANOAPP_USES_WIFI
64     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_WIFI)
65 #endif
66 #ifdef CHRE_NANOAPP_USES_WWAN
67     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_WWAN)
68 #endif
69 #endif  // CHRE_TEST_NANOAPP_PERMS
70     ;
71 
72 #if defined(CHRE_SLPI_UIMG_ENABLED) || defined(CHRE_TCM_ENABLED)
73 constexpr int kIsTcmNanoapp = 1;
74 #else
75 constexpr int kIsTcmNanoapp = 0;
76 #endif  // CHRE_SLPI_UIMG_ENABLED
77 
78 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) && defined(CHRE_NANOAPP_USES_GNSS)
79 // Return a v1.3+ GnssLocationEvent for the nanoapp when running on a v1.2-
80 // platform.
translateLegacyGnssLocation(const chreGnssLocationEvent & legacyEvent)81 chreGnssLocationEvent translateLegacyGnssLocation(
82     const chreGnssLocationEvent &legacyEvent) {
83   // Copy v1.2- fields over to a v1.3+ event.
84   chreGnssLocationEvent newEvent = {};
85   newEvent.timestamp = legacyEvent.timestamp;
86   newEvent.latitude_deg_e7 = legacyEvent.latitude_deg_e7;
87   newEvent.longitude_deg_e7 = legacyEvent.longitude_deg_e7;
88   newEvent.altitude = legacyEvent.altitude;
89   newEvent.speed = legacyEvent.speed;
90   newEvent.bearing = legacyEvent.bearing;
91   newEvent.accuracy = legacyEvent.accuracy;
92   newEvent.flags = legacyEvent.flags;
93 
94   // Unset flags that are defined in v1.3+ but not in v1.2-.
95   newEvent.flags &= ~(CHRE_GPS_LOCATION_HAS_ALTITUDE_ACCURACY |
96                       CHRE_GPS_LOCATION_HAS_SPEED_ACCURACY |
97                       CHRE_GPS_LOCATION_HAS_BEARING_ACCURACY);
98   return newEvent;
99 }
100 
nanoappHandleEventCompat(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)101 void nanoappHandleEventCompat(uint32_t senderInstanceId, uint16_t eventType,
102                               const void *eventData) {
103   if (eventType == CHRE_EVENT_GNSS_LOCATION &&
104       chreGetApiVersion() < CHRE_API_VERSION_1_3) {
105     chreGnssLocationEvent event = translateLegacyGnssLocation(
106         *static_cast<const chreGnssLocationEvent *>(eventData));
107     nanoappHandleEvent(senderInstanceId, eventType, &event);
108   } else {
109     nanoappHandleEvent(senderInstanceId, eventType, eventData);
110   }
111 }
112 #endif
113 
114 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) && \
115     defined(CHRE_NANOAPP_USES_BLE) &&            \
116     defined(CHRE_FIRST_SUPPORTED_API_VERSION) && \
117     CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
reverseServiceDataUuid(struct chreBleGenericFilter * filter)118 void reverseServiceDataUuid(struct chreBleGenericFilter *filter) {
119   if (filter->type != CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16_LE ||
120       filter->len == 0) {
121     return;
122   }
123   std::swap(filter->data[0], filter->data[1]);
124   std::swap(filter->dataMask[0], filter->dataMask[1]);
125   if (filter->len == 1) {
126     filter->data[0] = 0x0;
127     filter->dataMask[0] = 0x0;
128     filter->len = 2;
129   }
130 }
131 
serviceDataFilterEndianSwapRequired(const struct chreBleScanFilter * filter)132 bool serviceDataFilterEndianSwapRequired(
133     const struct chreBleScanFilter *filter) {
134   if (chreGetApiVersion() >= CHRE_API_VERSION_1_8 || filter == nullptr) {
135     return false;
136   }
137   for (size_t i = 0; i < filter->scanFilterCount; i++) {
138     if (filter->scanFilters[i].type ==
139             CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16_LE &&
140         filter->scanFilters[i].len > 0) {
141       return true;
142     }
143   }
144   return false;
145 }
146 #endif  // !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) &&
147         // defined(CHRE_NANOAPP_USES_BLE) &&
148         // defined(CHRE_FIRST_SUPPORTED_API_VERSION) &&
149         // CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
150 
151 }  // anonymous namespace
152 
153 //! Used to determine the given unstable ID that was provided when building this
154 //! nanoapp, if any. The symbol is placed in its own section so it can be
155 //! stripped to determine if the nanoapp changed compared to a previous version.
156 //! We also align the variable to match the minimum alignment of the surrounding
157 //! sections, since for compilers with a default size-1 alignment, there might
158 //! be a spill-over from the previous segment if not zero-padded, when we
159 //! attempt to read the string.
160 extern "C" DLL_EXPORT const char _chreNanoappUnstableId[]
161     __attribute__((section(".unstable_id"))) __attribute__((aligned(8))) =
162         NANOAPP_UNSTABLE_ID;
163 
164 extern "C" DLL_EXPORT const struct chreNslNanoappInfo _chreNslDsoNanoappInfo = {
165     /* magic */ CHRE_NSL_NANOAPP_INFO_MAGIC,
166     /* structMinorVersion */ CHRE_NSL_NANOAPP_INFO_STRUCT_MINOR_VERSION,
167     /* isSystemNanoapp */ NANOAPP_IS_SYSTEM_NANOAPP,
168     /* isTcmNanoapp */ kIsTcmNanoapp,
169     /* reservedFlags */ 0,
170     /* reserved */ 0,
171     /* targetApiVersion */ CHRE_API_VERSION,
172 
173     // These values are supplied by the build environment.
174     /* vendor */ NANOAPP_VENDOR_STRING,
175     /* name */ NANOAPP_NAME_STRING,
176     /* appId */ NANOAPP_ID,
177     /* appVersion */ NANOAPP_VERSION,
178     /* entryPoints */
179     {
180         /* start */ nanoappStart,
181 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) && defined(CHRE_NANOAPP_USES_GNSS)
182         /* handleEvent */ nanoappHandleEventCompat,
183 #else
184         /* handleEvent */ nanoappHandleEvent,
185 #endif
186         /* end */ nanoappEnd,
187     },
188     /* appVersionString */ _chreNanoappUnstableId,
189     /* appPermissions */ kNanoappPermissions,
190 };
191 
getChreNslDsoNanoappInfo()192 const struct chreNslNanoappInfo *getChreNslDsoNanoappInfo() {
193   return &_chreNslDsoNanoappInfo;
194 }
195 
196 // The code section below provides default implementations for new symbols
197 // introduced in CHRE API v1.2+ to provide binary compatibility with previous
198 // CHRE implementations. Note that we don't presently include symbols for v1.1,
199 // as the current known set of CHRE platforms that use this NSL implementation
200 // are all v1.1+.
201 // If a nanoapp knows that it is only targeting the latest platform version, it
202 // can define the CHRE_NANOAPP_DISABLE_BACKCOMPAT flag, so this indirection will
203 // be avoided at the expense of a nanoapp not being able to load at all on prior
204 // implementations.
205 
206 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT)
207 
208 #if !defined(CHRE_FIRST_SUPPORTED_API_VERSION)
209 #error "CHRE_FIRST_SUPPORTED_API_VERSION must be defined for this platform"
210 #elif CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_1
211 #error "CHRE_FIRST_SUPPORTED_API_VERSION must be at least CHRE_API_VERSION_1_1"
212 #endif  // !defined(CHRE_FIRST_SUPPORTED_API_VERSION)
213 
214 #include <dlfcn.h>
215 
216 namespace {
217 
218 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
219 // Populate chreNanoappInfo for CHRE API pre v1.8.
populateChreNanoappInfoPre18(struct chreNanoappInfo * info)220 void populateChreNanoappInfoPre18(struct chreNanoappInfo *info) {
221   info->rpcServiceCount = 0;
222   info->rpcServices = nullptr;
223   memset(&info->reserved, 0, sizeof(info->reserved));
224 }
225 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
226 
227 }  // namespace
228 
229 /**
230  * Lazily calls dlsym to find the function pointer for a given function
231  * (provided without quotes) in another library (i.e. the CHRE platform DSO),
232  * caching and returning the result.
233  */
234 #define CHRE_NSL_LAZY_LOOKUP(functionName)            \
235   ({                                                  \
236     static bool lookupPerformed = false;              \
237     static decltype(functionName) *funcPtr = nullptr; \
238     if (!lookupPerformed) {                           \
239       funcPtr = reinterpret_cast<decltype(funcPtr)>(  \
240           dlsym(RTLD_NEXT, STRINGIFY(functionName))); \
241       lookupPerformed = true;                         \
242     }                                                 \
243     funcPtr;                                          \
244   })
245 
246 #ifdef CHRE_NANOAPP_USES_AUDIO
247 
248 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
249 WEAK_SYMBOL
chreAudioGetSource(uint32_t handle,struct chreAudioSource * audioSource)250 bool chreAudioGetSource(uint32_t handle, struct chreAudioSource *audioSource) {
251   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetSource);
252   return (fptr != nullptr) ? fptr(handle, audioSource) : false;
253 }
254 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
255 
256 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
257 WEAK_SYMBOL
chreAudioConfigureSource(uint32_t handle,bool enable,uint64_t bufferDuration,uint64_t deliveryInterval)258 bool chreAudioConfigureSource(uint32_t handle, bool enable,
259                               uint64_t bufferDuration,
260                               uint64_t deliveryInterval) {
261   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioConfigureSource);
262   return (fptr != nullptr)
263              ? fptr(handle, enable, bufferDuration, deliveryInterval)
264              : false;
265 }
266 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
267 
268 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
269 WEAK_SYMBOL
chreAudioGetStatus(uint32_t handle,struct chreAudioSourceStatus * status)270 bool chreAudioGetStatus(uint32_t handle, struct chreAudioSourceStatus *status) {
271   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetStatus);
272   return (fptr != nullptr) ? fptr(handle, status) : false;
273 }
274 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
275 
276 #endif /* CHRE_NANOAPP_USES_AUDIO */
277 
278 #ifdef CHRE_NANOAPP_USES_BLE
279 
280 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
281 WEAK_SYMBOL
chreBleGetCapabilities()282 uint32_t chreBleGetCapabilities() {
283   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleGetCapabilities);
284   return (fptr != nullptr) ? fptr() : CHRE_BLE_CAPABILITIES_NONE;
285 }
286 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
287 
288 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
289 WEAK_SYMBOL
chreBleGetFilterCapabilities()290 uint32_t chreBleGetFilterCapabilities() {
291   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleGetFilterCapabilities);
292   return (fptr != nullptr) ? fptr() : CHRE_BLE_FILTER_CAPABILITIES_NONE;
293 }
294 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
295 
296 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_7
297 WEAK_SYMBOL
chreBleFlushAsync(const void * cookie)298 bool chreBleFlushAsync(const void *cookie) {
299   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleFlushAsync);
300   return (fptr != nullptr) ? fptr(cookie) : false;
301 }
302 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_7 */
303 
304 // NOTE: The backward compatibility provided by this stub is only needed below
305 // CHRE v1.8 so we check the first API version for the platform against v1.8.
306 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
307 WEAK_SYMBOL
chreBleStartScanAsync(chreBleScanMode mode,uint32_t reportDelayMs,const struct chreBleScanFilter * filter)308 bool chreBleStartScanAsync(chreBleScanMode mode, uint32_t reportDelayMs,
309                            const struct chreBleScanFilter *filter) {
310   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStartScanAsync);
311   if (fptr == nullptr) {
312     return false;
313   } else if (!serviceDataFilterEndianSwapRequired(filter)) {
314     return fptr(mode, reportDelayMs, filter);
315   }
316   // For nanoapps compiled against v1.8+ working with earlier versions of CHRE,
317   // convert service data filters to big-endian format.
318   chreBleScanFilter convertedFilter = *filter;
319   auto genericFilters = static_cast<chreBleGenericFilter *>(
320       chreHeapAlloc(sizeof(chreBleGenericFilter) * filter->scanFilterCount));
321   if (genericFilters == nullptr) {
322     chreLog(CHRE_LOG_ERROR, "Alloc failure in chreBleStartScanAsync NSL");
323     return false;
324   }
325   memcpy(genericFilters, filter->scanFilters,
326          filter->scanFilterCount * sizeof(chreBleGenericFilter));
327   for (size_t i = 0; i < filter->scanFilterCount; i++) {
328     reverseServiceDataUuid(&genericFilters[i]);
329   }
330   convertedFilter.scanFilters = genericFilters;
331   bool success = fptr(mode, reportDelayMs, &convertedFilter);
332   chreHeapFree(const_cast<chreBleGenericFilter *>(convertedFilter.scanFilters));
333   return success;
334 }
335 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
336 
337 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_9
338 WEAK_SYMBOL
chreBleStartScanAsyncV1_9(chreBleScanMode mode,uint32_t reportDelayMs,const struct chreBleScanFilterV1_9 * filter,const void * cookie)339 bool chreBleStartScanAsyncV1_9(chreBleScanMode mode, uint32_t reportDelayMs,
340                                const struct chreBleScanFilterV1_9 *filter,
341                                const void *cookie) {
342   if (chreGetApiVersion() < CHRE_API_VERSION_1_9) {
343     return false;
344   }
345   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStartScanAsyncV1_9);
346   if (fptr == nullptr) {
347     return false;
348   }
349   return fptr(mode, reportDelayMs, filter, cookie);
350 }
351 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_9 */
352 
353 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
354 WEAK_SYMBOL
chreBleStopScanAsync()355 bool chreBleStopScanAsync() {
356   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStopScanAsync);
357   return (fptr != nullptr) ? fptr() : false;
358 }
359 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
360 
361 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_9
362 WEAK_SYMBOL
chreBleStopScanAsyncV1_9(const void * cookie)363 bool chreBleStopScanAsyncV1_9(const void *cookie) {
364   if (chreGetApiVersion() < CHRE_API_VERSION_1_9) {
365     return false;
366   }
367   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStopScanAsyncV1_9);
368   if (fptr == nullptr) {
369     return false;
370   }
371   return fptr(cookie);
372 }
373 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_9 */
374 
375 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
376 WEAK_SYMBOL
chreBleReadRssiAsync(uint16_t connectionHandle,const void * cookie)377 bool chreBleReadRssiAsync(uint16_t connectionHandle, const void *cookie) {
378   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleReadRssiAsync);
379   return (fptr != nullptr) ? fptr(connectionHandle, cookie) : false;
380 }
381 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
382 
383 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
384 WEAK_SYMBOL
chreBleGetScanStatus(struct chreBleScanStatus * status)385 bool chreBleGetScanStatus(struct chreBleScanStatus *status) {
386   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleGetScanStatus);
387   return (fptr != nullptr) ? fptr(status) : false;
388 }
389 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
390 
391 #endif /* CHRE_NANOAPP_USES_BLE */
392 
393 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
394 WEAK_SYMBOL
chreConfigureHostSleepStateEvents(bool enable)395 void chreConfigureHostSleepStateEvents(bool enable) {
396   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostSleepStateEvents);
397   if (fptr != nullptr) {
398     fptr(enable);
399   }
400 }
401 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
402 
403 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
404 WEAK_SYMBOL
chreIsHostAwake(void)405 bool chreIsHostAwake(void) {
406   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreIsHostAwake);
407   return (fptr != nullptr) ? fptr() : false;
408 }
409 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
410 
411 #ifdef CHRE_NANOAPP_USES_GNSS
412 
413 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
414 WEAK_SYMBOL
chreGnssConfigurePassiveLocationListener(bool enable)415 bool chreGnssConfigurePassiveLocationListener(bool enable) {
416   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGnssConfigurePassiveLocationListener);
417   return (fptr != nullptr) ? fptr(enable) : false;
418 }
419 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
420 
421 #endif /* CHRE_NANOAPP_USES_GNSS */
422 
423 #ifdef CHRE_NANOAPP_USES_WIFI
424 
425 // NOTE: The backward compatibility provided by this stub is only needed below
426 // CHRE v1.5 so we check the first API version for the platform against v1.5.
427 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
428 WEAK_SYMBOL
chreWifiRequestScanAsync(const struct chreWifiScanParams * params,const void * cookie)429 bool chreWifiRequestScanAsync(const struct chreWifiScanParams *params,
430                               const void *cookie) {
431   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestScanAsync);
432 
433   if (fptr == nullptr) {
434     // Should never happen
435     return false;
436   } else if (chreGetApiVersion() < CHRE_API_VERSION_1_5) {
437     const struct chreWifiScanParams legacyParams =
438         chre::translateToLegacyWifiScanParams(params);
439     return fptr(&legacyParams, cookie);
440   } else {
441     return fptr(params, cookie);
442   }
443 }
444 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5 */
445 
446 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2
447 WEAK_SYMBOL
chreWifiRequestRangingAsync(const struct chreWifiRangingParams * params,const void * cookie)448 bool chreWifiRequestRangingAsync(const struct chreWifiRangingParams *params,
449                                  const void *cookie) {
450   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestRangingAsync);
451   return (fptr != nullptr) ? fptr(params, cookie) : false;
452 }
453 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_2 */
454 
455 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
456 WEAK_SYMBOL
chreWifiNanRequestRangingAsync(const struct chreWifiNanRangingParams * params,const void * cookie)457 bool chreWifiNanRequestRangingAsync(
458     const struct chreWifiNanRangingParams *params, const void *cookie) {
459   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanRequestRangingAsync);
460   return (fptr != nullptr) ? fptr(params, cookie) : false;
461 }
462 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
463 
464 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
465 WEAK_SYMBOL
chreWifiNanSubscribe(struct chreWifiNanSubscribeConfig * config,const void * cookie)466 bool chreWifiNanSubscribe(struct chreWifiNanSubscribeConfig *config,
467                           const void *cookie) {
468   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanSubscribe);
469   return (fptr != nullptr) ? fptr(config, cookie) : false;
470 }
471 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
472 
473 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
474 WEAK_SYMBOL
chreWifiNanSubscribeCancel(uint32_t subscriptionID)475 bool chreWifiNanSubscribeCancel(uint32_t subscriptionID) {
476   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanSubscribeCancel);
477   return (fptr != nullptr) ? fptr(subscriptionID) : false;
478 }
479 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
480 
481 #endif /* CHRE_NANOAPP_USES_WIFI */
482 
483 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
484 WEAK_SYMBOL
chreSensorFind(uint8_t sensorType,uint8_t sensorIndex,uint32_t * handle)485 bool chreSensorFind(uint8_t sensorType, uint8_t sensorIndex, uint32_t *handle) {
486   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFind);
487   if (fptr != nullptr) {
488     return fptr(sensorType, sensorIndex, handle);
489   } else if (sensorIndex == 0) {
490     return chreSensorFindDefault(sensorType, handle);
491   } else {
492     return false;
493   }
494 }
495 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5 */
496 
497 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3
498 WEAK_SYMBOL
chreSensorConfigureBiasEvents(uint32_t sensorHandle,bool enable)499 bool chreSensorConfigureBiasEvents(uint32_t sensorHandle, bool enable) {
500   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorConfigureBiasEvents);
501   return (fptr != nullptr) ? fptr(sensorHandle, enable) : false;
502 }
503 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3 */
504 
505 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3
506 WEAK_SYMBOL
chreSensorGetThreeAxisBias(uint32_t sensorHandle,struct chreSensorThreeAxisData * bias)507 bool chreSensorGetThreeAxisBias(uint32_t sensorHandle,
508                                 struct chreSensorThreeAxisData *bias) {
509   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorGetThreeAxisBias);
510   return (fptr != nullptr) ? fptr(sensorHandle, bias) : false;
511 }
512 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3 */
513 
514 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3
515 WEAK_SYMBOL
chreSensorFlushAsync(uint32_t sensorHandle,const void * cookie)516 bool chreSensorFlushAsync(uint32_t sensorHandle, const void *cookie) {
517   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFlushAsync);
518   return (fptr != nullptr) ? fptr(sensorHandle, cookie) : false;
519 }
520 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_3 */
521 
522 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_4
523 WEAK_SYMBOL
chreConfigureDebugDumpEvent(bool enable)524 void chreConfigureDebugDumpEvent(bool enable) {
525   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureDebugDumpEvent);
526   if (fptr != nullptr) {
527     fptr(enable);
528   }
529 }
530 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_4 */
531 
532 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_4
533 WEAK_SYMBOL
chreDebugDumpLog(const char * formatStr,...)534 void chreDebugDumpLog(const char *formatStr, ...) {
535   auto *fptr = CHRE_NSL_LAZY_LOOKUP(platform_chreDebugDumpVaLog);
536   if (fptr != nullptr) {
537     va_list args;
538     va_start(args, formatStr);
539     fptr(formatStr, args);
540     va_end(args);
541   }
542 }
543 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_4 */
544 
545 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
546 WEAK_SYMBOL
chreSendMessageWithPermissions(void * message,size_t messageSize,uint32_t messageType,uint16_t hostEndpoint,uint32_t messagePermissions,chreMessageFreeFunction * freeCallback)547 bool chreSendMessageWithPermissions(void *message, size_t messageSize,
548                                     uint32_t messageType, uint16_t hostEndpoint,
549                                     uint32_t messagePermissions,
550                                     chreMessageFreeFunction *freeCallback) {
551   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSendMessageWithPermissions);
552   if (fptr != nullptr) {
553     return fptr(message, messageSize, messageType, hostEndpoint,
554                 messagePermissions, freeCallback);
555   } else {
556     return chreSendMessageToHostEndpoint(message, messageSize, messageType,
557                                          hostEndpoint, freeCallback);
558   }
559 }
560 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5 */
561 
562 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10
563 WEAK_SYMBOL
chreSendReliableMessageAsync(void * message,size_t messageSize,uint32_t messageType,uint16_t hostEndpoint,uint32_t messagePermissions,chreMessageFreeFunction * freeCallback,const void * cookie)564 bool chreSendReliableMessageAsync(void *message, size_t messageSize,
565                                   uint32_t messageType, uint16_t hostEndpoint,
566                                   uint32_t messagePermissions,
567                                   chreMessageFreeFunction *freeCallback,
568                                   const void *cookie) {
569   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSendReliableMessageAsync);
570   if (fptr != nullptr) {
571     return fptr(message, messageSize, messageType, hostEndpoint,
572                 messagePermissions, freeCallback, cookie);
573   } else {
574     return false;
575   }
576 }
577 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10 */
578 
579 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
580 WEAK_SYMBOL
chreUserSettingGetState(uint8_t setting)581 int8_t chreUserSettingGetState(uint8_t setting) {
582   int8_t settingState = CHRE_USER_SETTING_STATE_UNKNOWN;
583   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreUserSettingGetState);
584   if (fptr != nullptr) {
585     settingState = fptr(setting);
586   }
587   return settingState;
588 }
589 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5 */
590 
591 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
592 WEAK_SYMBOL
chreUserSettingConfigureEvents(uint8_t setting,bool enable)593 void chreUserSettingConfigureEvents(uint8_t setting, bool enable) {
594   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreUserSettingConfigureEvents);
595   if (fptr != nullptr) {
596     fptr(setting, enable);
597   }
598 }
599 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5 */
600 
601 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
602 WEAK_SYMBOL
chreConfigureHostEndpointNotifications(uint16_t hostEndpointId,bool enable)603 bool chreConfigureHostEndpointNotifications(uint16_t hostEndpointId,
604                                             bool enable) {
605   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostEndpointNotifications);
606   return (fptr != nullptr) ? fptr(hostEndpointId, enable) : false;
607 }
608 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
609 
610 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
611 WEAK_SYMBOL
chrePublishRpcServices(struct chreNanoappRpcService * services,size_t numServices)612 bool chrePublishRpcServices(struct chreNanoappRpcService *services,
613                             size_t numServices) {
614   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chrePublishRpcServices);
615   return (fptr != nullptr) ? fptr(services, numServices) : false;
616 }
617 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
618 
619 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6
620 WEAK_SYMBOL
chreGetHostEndpointInfo(uint16_t hostEndpointId,struct chreHostEndpointInfo * info)621 bool chreGetHostEndpointInfo(uint16_t hostEndpointId,
622                              struct chreHostEndpointInfo *info) {
623   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetHostEndpointInfo);
624   return (fptr != nullptr) ? fptr(hostEndpointId, info) : false;
625 }
626 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_6 */
627 
628 // NOTE: The backward compatibility provided by this stub is only needed below
629 // CHRE v1.8 so we check the first API version for the platform against v1.8.
630 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
chreGetNanoappInfoByAppId(uint64_t appId,struct chreNanoappInfo * info)631 bool chreGetNanoappInfoByAppId(uint64_t appId, struct chreNanoappInfo *info) {
632   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetNanoappInfoByAppId);
633   bool success = (fptr != nullptr) ? fptr(appId, info) : false;
634   if (success && chreGetApiVersion() < CHRE_API_VERSION_1_8) {
635     populateChreNanoappInfoPre18(info);
636   }
637   return success;
638 }
639 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
640 
641 // NOTE: The backward compatibility provided by this stub is only needed below
642 // CHRE v1.8 so we check the first API version for the platform against v1.8.
643 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8
chreGetNanoappInfoByInstanceId(uint32_t instanceId,struct chreNanoappInfo * info)644 bool chreGetNanoappInfoByInstanceId(uint32_t instanceId,
645                                     struct chreNanoappInfo *info) {
646   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetNanoappInfoByInstanceId);
647   bool success = (fptr != nullptr) ? fptr(instanceId, info) : false;
648   if (success && chreGetApiVersion() < CHRE_API_VERSION_1_8) {
649     populateChreNanoappInfoPre18(info);
650   }
651   return success;
652 }
653 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_8 */
654 
655 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10
656 WEAK_SYMBOL
chreGetCapabilities()657 uint32_t chreGetCapabilities() {
658   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetCapabilities);
659   return (fptr != nullptr) ? fptr() : CHRE_CAPABILITIES_NONE;
660 }
661 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10 */
662 
663 #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10
664 WEAK_SYMBOL
chreGetMessageToHostMaxSize()665 uint32_t chreGetMessageToHostMaxSize() {
666   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetMessageToHostMaxSize);
667   return (fptr != nullptr) ? fptr() : CHRE_MESSAGE_TO_HOST_MAX_SIZE;
668 }
669 #endif /* CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_10 */
670 
671 #endif  // !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT)
672