• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <chre.h>
25 
26 #include "chre_nsl_internal/platform/shared/debug_dump.h"
27 #include "chre_nsl_internal/util/macros.h"
28 #include "chre_nsl_internal/util/system/napp_permissions.h"
29 #ifdef CHRE_NANOAPP_USES_WIFI
30 #include "chre_nsl_internal/util/system/wifi_util.h"
31 #endif
32 
33 /**
34  * @file
35  * The Nanoapp Support Library (NSL) that gets built with nanoapps to act as an
36  * intermediary to the reference CHRE implementation. It provides hooks so the
37  * app can be registered with the system, and also provides a layer where we can
38  * implement cross-version compatibility features as needed.
39  */
40 
41 namespace {
42 
43 constexpr uint32_t kNanoappPermissions = 0
44 // DO NOT USE this macro outside of specific CHQTS nanoapps. This is only used
45 // to allow testing of invalid permission declarations.
46 #ifdef CHRE_TEST_NANOAPP_PERMS
47                                          | CHRE_TEST_NANOAPP_PERMS
48 #else
49 #ifdef CHRE_NANOAPP_USES_AUDIO
50     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_AUDIO)
51 #endif
52 #ifdef CHRE_NANOAPP_USES_BLE
53     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_BLE)
54 #endif
55 #ifdef CHRE_NANOAPP_USES_GNSS
56     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_GNSS)
57 #endif
58 #ifdef CHRE_NANOAPP_USES_WIFI
59     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_WIFI)
60 #endif
61 #ifdef CHRE_NANOAPP_USES_WWAN
62     | static_cast<uint32_t>(chre::NanoappPermissions::CHRE_PERMS_WWAN)
63 #endif
64 #endif  // CHRE_TEST_NANOAPP_PERMS
65     ;
66 
67 #if defined(CHRE_SLPI_UIMG_ENABLED) || defined(CHRE_TCM_ENABLED)
68 constexpr int kIsTcmNanoapp = 1;
69 #else
70 constexpr int kIsTcmNanoapp = 0;
71 #endif  // CHRE_SLPI_UIMG_ENABLED
72 
73 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) && defined(CHRE_NANOAPP_USES_GNSS)
74 // Return a v1.3+ GnssLocationEvent for the nanoapp when running on a v1.2-
75 // platform.
translateLegacyGnssLocation(const chreGnssLocationEvent & legacyEvent)76 chreGnssLocationEvent translateLegacyGnssLocation(
77     const chreGnssLocationEvent &legacyEvent) {
78   // Copy v1.2- fields over to a v1.3+ event.
79   chreGnssLocationEvent newEvent = {};
80   newEvent.timestamp = legacyEvent.timestamp;
81   newEvent.latitude_deg_e7 = legacyEvent.latitude_deg_e7;
82   newEvent.longitude_deg_e7 = legacyEvent.longitude_deg_e7;
83   newEvent.altitude = legacyEvent.altitude;
84   newEvent.speed = legacyEvent.speed;
85   newEvent.bearing = legacyEvent.bearing;
86   newEvent.accuracy = legacyEvent.accuracy;
87   newEvent.flags = legacyEvent.flags;
88 
89   // Unset flags that are defined in v1.3+ but not in v1.2-.
90   newEvent.flags &= ~(CHRE_GPS_LOCATION_HAS_ALTITUDE_ACCURACY |
91                       CHRE_GPS_LOCATION_HAS_SPEED_ACCURACY |
92                       CHRE_GPS_LOCATION_HAS_BEARING_ACCURACY);
93   return newEvent;
94 }
95 
nanoappHandleEventCompat(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)96 void nanoappHandleEventCompat(uint32_t senderInstanceId, uint16_t eventType,
97                               const void *eventData) {
98   if (eventType == CHRE_EVENT_GNSS_LOCATION &&
99       chreGetApiVersion() < CHRE_API_VERSION_1_3) {
100     chreGnssLocationEvent event = translateLegacyGnssLocation(
101         *static_cast<const chreGnssLocationEvent *>(eventData));
102     nanoappHandleEvent(senderInstanceId, eventType, &event);
103   } else {
104     nanoappHandleEvent(senderInstanceId, eventType, eventData);
105   }
106 }
107 #endif
108 
109 }  // anonymous namespace
110 
111 //! Used to determine the given unstable ID that was provided when building this
112 //! nanoapp, if any. The symbol is placed in its own section so it can be
113 //! stripped to determine if the nanoapp changed compared to a previous version.
114 //! We also align the variable to match the minimum alignment of the surrounding
115 //! sections, since for compilers with a default size-1 alignment, there might
116 //! be a spill-over from the previous segment if not zero-padded, when we
117 //! attempt to read the string.
118 DLL_EXPORT extern "C" const char _chreNanoappUnstableId[]
119     __attribute__((section(".unstable_id"))) __attribute__((aligned(8))) =
120         NANOAPP_UNSTABLE_ID;
121 
122 DLL_EXPORT extern "C" const struct chreNslNanoappInfo _chreNslDsoNanoappInfo = {
123     /* magic */ CHRE_NSL_NANOAPP_INFO_MAGIC,
124     /* structMinorVersion */ CHRE_NSL_NANOAPP_INFO_STRUCT_MINOR_VERSION,
125     /* isSystemNanoapp */ NANOAPP_IS_SYSTEM_NANOAPP,
126     /* isTcmNanoapp */ kIsTcmNanoapp,
127     /* reservedFlags */ 0,
128     /* reserved */ 0,
129     /* targetApiVersion */ CHRE_API_VERSION,
130 
131     // These values are supplied by the build environment.
132     /* vendor */ NANOAPP_VENDOR_STRING,
133     /* name */ NANOAPP_NAME_STRING,
134     /* appId */ NANOAPP_ID,
135     /* appVersion */ NANOAPP_VERSION,
136     /* entryPoints */
137     {
138         /* start */ nanoappStart,
139 #if !defined(CHRE_NANOAPP_DISABLE_BACKCOMPAT) && defined(CHRE_NANOAPP_USES_GNSS)
140         /* handleEvent */ nanoappHandleEventCompat,
141 #else
142         /* handleEvent */ nanoappHandleEvent,
143 #endif
144         /* end */ nanoappEnd,
145     },
146     /* appVersionString */ _chreNanoappUnstableId,
147     /* appPermissions */ kNanoappPermissions,
148 };
149 
150 // The code section below provides default implementations for new symbols
151 // introduced in CHRE API v1.2+ to provide binary compatibility with previous
152 // CHRE implementations. Note that we don't presently include symbols for v1.1,
153 // as the current known set of CHRE platforms that use this NSL implementation
154 // are all v1.1+.
155 // If a nanoapp knows that it is only targeting the latest platform version, it
156 // can define the CHRE_NANOAPP_DISABLE_BACKCOMPAT flag, so this indirection will
157 // be avoided at the expense of a nanoapp not being able to load at all on prior
158 // implementations.
159 
160 #ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
161 
162 #include <dlfcn.h>
163 
164 /**
165  * Lazily calls dlsym to find the function pointer for a given function
166  * (provided without quotes) in another library (i.e. the CHRE platform DSO),
167  * caching and returning the result.
168  */
169 #define CHRE_NSL_LAZY_LOOKUP(functionName)            \
170   ({                                                  \
171     static bool lookupPerformed = false;              \
172     static decltype(functionName) *funcPtr = nullptr; \
173     if (!lookupPerformed) {                           \
174       funcPtr = reinterpret_cast<decltype(funcPtr)>(  \
175           dlsym(RTLD_NEXT, STRINGIFY(functionName))); \
176       lookupPerformed = true;                         \
177     }                                                 \
178     funcPtr;                                          \
179   })
180 
181 #ifdef CHRE_NANOAPP_USES_AUDIO
182 
183 WEAK_SYMBOL
chreAudioGetSource(uint32_t handle,struct chreAudioSource * audioSource)184 bool chreAudioGetSource(uint32_t handle, struct chreAudioSource *audioSource) {
185   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetSource);
186   return (fptr != nullptr) ? fptr(handle, audioSource) : false;
187 }
188 
189 WEAK_SYMBOL
chreAudioConfigureSource(uint32_t handle,bool enable,uint64_t bufferDuration,uint64_t deliveryInterval)190 bool chreAudioConfigureSource(uint32_t handle, bool enable,
191                               uint64_t bufferDuration,
192                               uint64_t deliveryInterval) {
193   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioConfigureSource);
194   return (fptr != nullptr)
195              ? fptr(handle, enable, bufferDuration, deliveryInterval)
196              : false;
197 }
198 
199 WEAK_SYMBOL
chreAudioGetStatus(uint32_t handle,struct chreAudioSourceStatus * status)200 bool chreAudioGetStatus(uint32_t handle, struct chreAudioSourceStatus *status) {
201   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetStatus);
202   return (fptr != nullptr) ? fptr(handle, status) : false;
203 }
204 
205 #endif /* CHRE_NANOAPP_USES_AUDIO */
206 
207 #ifdef CHRE_NANOAPP_USES_BLE
208 
209 WEAK_SYMBOL
chreBleGetCapabilities()210 uint32_t chreBleGetCapabilities() {
211   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleGetCapabilities);
212   return (fptr != nullptr) ? fptr() : CHRE_BLE_CAPABILITIES_NONE;
213 }
214 
215 WEAK_SYMBOL
chreBleGetFilterCapabilities()216 uint32_t chreBleGetFilterCapabilities() {
217   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleGetFilterCapabilities);
218   return (fptr != nullptr) ? fptr() : CHRE_BLE_FILTER_CAPABILITIES_NONE;
219 }
220 
221 WEAK_SYMBOL
chreBleStartScanAsync(chreBleScanMode mode,uint32_t reportDelayMs,const struct chreBleScanFilter * filter)222 bool chreBleStartScanAsync(chreBleScanMode mode, uint32_t reportDelayMs,
223                            const struct chreBleScanFilter *filter) {
224   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStartScanAsync);
225   return (fptr != nullptr) ? fptr(mode, reportDelayMs, filter) : false;
226 }
227 
228 WEAK_SYMBOL
chreBleStopScanAsync()229 bool chreBleStopScanAsync() {
230   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreBleStopScanAsync);
231   return (fptr != nullptr) ? fptr() : false;
232 }
233 
234 #endif /* CHRE_NANOAPP_USES_BLE */
235 
236 WEAK_SYMBOL
chreConfigureHostSleepStateEvents(bool enable)237 void chreConfigureHostSleepStateEvents(bool enable) {
238   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostSleepStateEvents);
239   if (fptr != nullptr) {
240     fptr(enable);
241   }
242 }
243 
244 WEAK_SYMBOL
chreIsHostAwake(void)245 bool chreIsHostAwake(void) {
246   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreIsHostAwake);
247   return (fptr != nullptr) ? fptr() : false;
248 }
249 
250 #ifdef CHRE_NANOAPP_USES_GNSS
251 
252 WEAK_SYMBOL
chreGnssConfigurePassiveLocationListener(bool enable)253 bool chreGnssConfigurePassiveLocationListener(bool enable) {
254   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGnssConfigurePassiveLocationListener);
255   return (fptr != nullptr) ? fptr(enable) : false;
256 }
257 
258 #endif /* CHRE_NANOAPP_USES_GNSS */
259 
260 #ifdef CHRE_NANOAPP_USES_WIFI
261 
262 WEAK_SYMBOL
chreWifiRequestScanAsync(const struct chreWifiScanParams * params,const void * cookie)263 bool chreWifiRequestScanAsync(const struct chreWifiScanParams *params,
264                               const void *cookie) {
265   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestScanAsync);
266 
267   if (fptr == nullptr) {
268     // Should never happen
269     return false;
270   } else if (chreGetApiVersion() < CHRE_API_VERSION_1_5) {
271     const struct chreWifiScanParams legacyParams =
272         chre::translateToLegacyWifiScanParams(params);
273     return fptr(&legacyParams, cookie);
274   } else {
275     return fptr(params, cookie);
276   }
277 }
278 
279 WEAK_SYMBOL
chreWifiRequestRangingAsync(const struct chreWifiRangingParams * params,const void * cookie)280 bool chreWifiRequestRangingAsync(const struct chreWifiRangingParams *params,
281                                  const void *cookie) {
282   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestRangingAsync);
283   return (fptr != nullptr) ? fptr(params, cookie) : false;
284 }
285 
286 WEAK_SYMBOL
chreWifiNanRequestRangingAsync(const struct chreWifiNanRangingParams * params,const void * cookie)287 bool chreWifiNanRequestRangingAsync(
288     const struct chreWifiNanRangingParams *params, const void *cookie) {
289   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanRequestRangingAsync);
290   return (fptr != nullptr) ? fptr(params, cookie) : false;
291 }
292 
293 WEAK_SYMBOL
chreWifiNanSubscribe(struct chreWifiNanSubscribeConfig * config,const void * cookie)294 bool chreWifiNanSubscribe(struct chreWifiNanSubscribeConfig *config,
295                           const void *cookie) {
296   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanSubscribe);
297   return (fptr != nullptr) ? fptr(config, cookie) : false;
298 }
299 
300 WEAK_SYMBOL
chreWifiNanSubscribeCancel(uint32_t subscriptionID)301 bool chreWifiNanSubscribeCancel(uint32_t subscriptionID) {
302   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiNanSubscribeCancel);
303   return (fptr != nullptr) ? fptr(subscriptionID) : false;
304 }
305 
306 #endif /* CHRE_NANOAPP_USES_WIFI */
307 
308 WEAK_SYMBOL
chreSensorFind(uint8_t sensorType,uint8_t sensorIndex,uint32_t * handle)309 bool chreSensorFind(uint8_t sensorType, uint8_t sensorIndex, uint32_t *handle) {
310   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFind);
311   if (fptr != nullptr) {
312     return fptr(sensorType, sensorIndex, handle);
313   } else if (sensorIndex == 0) {
314     return chreSensorFindDefault(sensorType, handle);
315   } else {
316     return false;
317   }
318 }
319 
320 WEAK_SYMBOL
chreSensorConfigureBiasEvents(uint32_t sensorHandle,bool enable)321 bool chreSensorConfigureBiasEvents(uint32_t sensorHandle, bool enable) {
322   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorConfigureBiasEvents);
323   return (fptr != nullptr) ? fptr(sensorHandle, enable) : false;
324 }
325 
326 WEAK_SYMBOL
chreSensorGetThreeAxisBias(uint32_t sensorHandle,struct chreSensorThreeAxisData * bias)327 bool chreSensorGetThreeAxisBias(uint32_t sensorHandle,
328                                 struct chreSensorThreeAxisData *bias) {
329   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorGetThreeAxisBias);
330   return (fptr != nullptr) ? fptr(sensorHandle, bias) : false;
331 }
332 
333 WEAK_SYMBOL
chreSensorFlushAsync(uint32_t sensorHandle,const void * cookie)334 bool chreSensorFlushAsync(uint32_t sensorHandle, const void *cookie) {
335   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFlushAsync);
336   return (fptr != nullptr) ? fptr(sensorHandle, cookie) : false;
337 }
338 
339 WEAK_SYMBOL
chreConfigureDebugDumpEvent(bool enable)340 void chreConfigureDebugDumpEvent(bool enable) {
341   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureDebugDumpEvent);
342   if (fptr != nullptr) {
343     fptr(enable);
344   }
345 }
346 
347 WEAK_SYMBOL
chreDebugDumpLog(const char * formatStr,...)348 void chreDebugDumpLog(const char *formatStr, ...) {
349   auto *fptr = CHRE_NSL_LAZY_LOOKUP(platform_chreDebugDumpVaLog);
350   if (fptr != nullptr) {
351     va_list args;
352     va_start(args, formatStr);
353     fptr(formatStr, args);
354     va_end(args);
355   }
356 }
357 
358 WEAK_SYMBOL
chreSendMessageWithPermissions(void * message,size_t messageSize,uint32_t messageType,uint16_t hostEndpoint,uint32_t messagePermissions,chreMessageFreeFunction * freeCallback)359 bool chreSendMessageWithPermissions(void *message, size_t messageSize,
360                                     uint32_t messageType, uint16_t hostEndpoint,
361                                     uint32_t messagePermissions,
362                                     chreMessageFreeFunction *freeCallback) {
363   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSendMessageWithPermissions);
364   if (fptr != nullptr) {
365     return fptr(message, messageSize, messageType, hostEndpoint,
366                 messagePermissions, freeCallback);
367   } else {
368     return chreSendMessageToHostEndpoint(message, messageSize, messageType,
369                                          hostEndpoint, freeCallback);
370   }
371 }
372 
373 WEAK_SYMBOL
chreUserSettingGetState(uint8_t setting)374 int8_t chreUserSettingGetState(uint8_t setting) {
375   int8_t settingState = CHRE_USER_SETTING_STATE_UNKNOWN;
376   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreUserSettingGetState);
377   if (fptr != nullptr) {
378     settingState = fptr(setting);
379   }
380   return settingState;
381 }
382 
383 WEAK_SYMBOL
chreUserSettingConfigureEvents(uint8_t setting,bool enable)384 void chreUserSettingConfigureEvents(uint8_t setting, bool enable) {
385   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreUserSettingConfigureEvents);
386   if (fptr != nullptr) {
387     fptr(setting, enable);
388   }
389 }
390 
391 WEAK_SYMBOL
chreConfigureHostEndpointNotifications(uint16_t hostEndpointId,bool enable)392 bool chreConfigureHostEndpointNotifications(uint16_t hostEndpointId,
393                                             bool enable) {
394   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostEndpointNotifications);
395   return (fptr != nullptr) ? fptr(hostEndpointId, enable) : false;
396 }
397 
398 WEAK_SYMBOL
chrePublishRpcServices(struct chreNanoappRpcService * services,size_t numServices)399 bool chrePublishRpcServices(struct chreNanoappRpcService *services,
400                             size_t numServices) {
401   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chrePublishRpcServices);
402   return (fptr != nullptr) ? fptr(services, numServices) : false;
403 }
404 
405 WEAK_SYMBOL
chreGetHostEndpointInfo(uint16_t hostEndpointId,struct chreHostEndpointInfo * info)406 bool chreGetHostEndpointInfo(uint16_t hostEndpointId,
407                              struct chreHostEndpointInfo *info) {
408   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGetHostEndpointInfo);
409   return (fptr != nullptr) ? fptr(hostEndpointId, info) : false;
410 }
411 
412 #endif  // CHRE_NANOAPP_DISABLE_BACKCOMPAT
413