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 #include "chre/platform/shared/nanoapp_support_lib_dso.h"
18 
19 #include <chre.h>
20 
21 #include "chre/util/macros.h"
22 
23 /**
24  * @file
25  * The Nanoapp Support Library (NSL) that gets built with nanoapps to act as an
26  * intermediary to the reference CHRE implementation. It provides hooks so the
27  * app can be registered with the system, and also provides a layer where we can
28  * implement cross-version compatibility features as needed.
29  */
30 
31 namespace {
32 
33 #ifdef CHRE_SLPI_UIMG_ENABLED
34 constexpr int kIsTcmNanoapp = 1;
35 #else
36 constexpr int kIsTcmNanoapp = 0;
37 #endif  // CHRE_SLPI_UIMG_ENABLED
38 
39 #ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
40 // Return a v1.3+ GnssLocationEvent for the nanoapp when running on a v1.2-
41 // platform.
translateLegacyGnssLocation(const chreGnssLocationEvent & legacyEvent)42 chreGnssLocationEvent translateLegacyGnssLocation(
43     const chreGnssLocationEvent& legacyEvent) {
44   // Copy v1.2- fields over to a v1.3+ event.
45   chreGnssLocationEvent newEvent = {};
46   newEvent.timestamp = legacyEvent.timestamp;
47   newEvent.latitude_deg_e7 = legacyEvent.latitude_deg_e7;
48   newEvent.longitude_deg_e7 = legacyEvent.longitude_deg_e7;
49   newEvent.altitude = legacyEvent.altitude;
50   newEvent.speed = legacyEvent.speed;
51   newEvent.bearing = legacyEvent.bearing;
52   newEvent.accuracy = legacyEvent.accuracy;
53   newEvent.flags = legacyEvent.flags;
54 
55   // Unset flags that are defined in v1.3+ but not in v1.2-.
56   newEvent.flags &= ~(CHRE_GPS_LOCATION_HAS_ALTITUDE_ACCURACY
57                       | CHRE_GPS_LOCATION_HAS_SPEED_ACCURACY
58                       | CHRE_GPS_LOCATION_HAS_BEARING_ACCURACY);
59   return newEvent;
60 }
61 
nanoappHandleEventCompat(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)62 void nanoappHandleEventCompat(uint32_t senderInstanceId, uint16_t eventType,
63                               const void *eventData) {
64   if (eventType == CHRE_EVENT_GNSS_LOCATION
65       && chreGetApiVersion() < CHRE_API_VERSION_1_3) {
66     chreGnssLocationEvent event = translateLegacyGnssLocation(
67         *static_cast<const chreGnssLocationEvent *>(eventData));
68     nanoappHandleEvent(senderInstanceId, eventType, &event);
69   } else {
70     nanoappHandleEvent(senderInstanceId, eventType, eventData);
71   }
72 }
73 #endif
74 
75 }  // anonymous namespace
76 
77 DLL_EXPORT extern "C" const struct chreNslNanoappInfo _chreNslDsoNanoappInfo = {
78   /* magic */ CHRE_NSL_NANOAPP_INFO_MAGIC,
79   /* structMinorVersion */ CHRE_NSL_NANOAPP_INFO_STRUCT_MINOR_VERSION,
80   /* isSystemNanoapp */ NANOAPP_IS_SYSTEM_NANOAPP,
81   /* isTcmNanoapp */ kIsTcmNanoapp,
82   /* reservedFlags */ 0,
83   /* reserved */ 0,
84   /* targetApiVersion */ CHRE_API_VERSION,
85 
86   // These values are supplied by the build environment.
87   /* vendor */ NANOAPP_VENDOR_STRING,
88   /* name */ NANOAPP_NAME_STRING,
89   /* appId */ NANOAPP_ID,
90   /* appVersion */ NANOAPP_VERSION,
91   /* entryPoints */ {
92     /* start */ nanoappStart,
93 #ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
94     /* handleEvent */ nanoappHandleEventCompat,
95 #else
96     /* handleEvent */ nanoappHandleEvent,
97 #endif
98     /* end */ nanoappEnd,
99   },
100   /* appVersionString */ NANOAPP_VERSION_STRING,
101 };
102 
103 // The code section below provides default implementations for new symbols
104 // introduced in CHRE API v1.2+ to provide binary compatibility with previous
105 // CHRE implementations. Note that we don't presently include symbols for v1.1,
106 // as the current known set of CHRE platforms that use this NSL implementation
107 // are all v1.1+.
108 // If a nanoapp knows that it is only targeting the latest platform version, it
109 // can define the CHRE_NANOAPP_DISABLE_BACKCOMPAT flag, so this indirection will
110 // be avoided at the expense of a nanoapp not being able to load at all on prior
111 // implementations.
112 
113 #ifndef CHRE_NANOAPP_DISABLE_BACKCOMPAT
114 
115 #include <dlfcn.h>
116 
117 /**
118  * Lazily calls dlsym to find the function pointer for a given function
119  * (provided without quotes) in another library (i.e. the CHRE platform DSO),
120  * caching and returning the result.
121  */
122 #define CHRE_NSL_LAZY_LOOKUP(functionName) ({         \
123     static bool lookupPerformed = false;              \
124     static decltype(functionName) *fptr = nullptr;    \
125     if (!lookupPerformed) {                           \
126       fptr = reinterpret_cast<decltype(fptr)>(        \
127           dlsym(RTLD_NEXT, STRINGIFY(functionName))); \
128       lookupPerformed = true;                         \
129     }                                                 \
130     fptr; })
131 
132 WEAK_SYMBOL
chreAudioGetSource(uint32_t handle,struct chreAudioSource * audioSource)133 bool chreAudioGetSource(uint32_t handle, struct chreAudioSource *audioSource) {
134   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetSource);
135   return (fptr != nullptr) ? fptr(handle, audioSource) : false;
136 }
137 
138 WEAK_SYMBOL
chreAudioConfigureSource(uint32_t handle,bool enable,uint64_t bufferDuration,uint64_t deliveryInterval)139 bool chreAudioConfigureSource(uint32_t handle, bool enable,
140                               uint64_t bufferDuration,
141                               uint64_t deliveryInterval) {
142   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioConfigureSource);
143   return (fptr != nullptr) ?
144       fptr(handle, enable, bufferDuration, deliveryInterval) : false;
145 }
146 
147 WEAK_SYMBOL
chreAudioGetStatus(uint32_t handle,struct chreAudioSourceStatus * status)148 bool chreAudioGetStatus(uint32_t handle, struct chreAudioSourceStatus *status) {
149   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreAudioGetStatus);
150   return (fptr != nullptr) ? fptr(handle, status) : false;
151 }
152 
153 WEAK_SYMBOL
chreConfigureHostSleepStateEvents(bool enable)154 void chreConfigureHostSleepStateEvents(bool enable) {
155   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreConfigureHostSleepStateEvents);
156   if (fptr != nullptr) {
157     fptr(enable);
158   }
159 }
160 
161 WEAK_SYMBOL
chreIsHostAwake(void)162 bool chreIsHostAwake(void) {
163   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreIsHostAwake);
164   return (fptr != nullptr) ? fptr() : false;
165 }
166 
167 WEAK_SYMBOL
chreGnssConfigureLocationMonitor(bool enable)168 bool chreGnssConfigureLocationMonitor(bool enable) {
169   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreGnssConfigureLocationMonitor);
170   return (fptr != nullptr) ? fptr(enable) : false;
171 }
172 
173 WEAK_SYMBOL
chreWifiRequestRangingAsync(const struct chreWifiRangingParams * params,const void * cookie)174 bool chreWifiRequestRangingAsync(const struct chreWifiRangingParams *params,
175                                  const void *cookie) {
176   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreWifiRequestRangingAsync);
177   return (fptr != nullptr) ? fptr(params, cookie) : false;
178 }
179 
180 WEAK_SYMBOL
chreSensorConfigureBiasEvents(uint32_t sensorHandle,bool enable)181 bool chreSensorConfigureBiasEvents(uint32_t sensorHandle, bool enable) {
182   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorConfigureBiasEvents);
183   return (fptr != nullptr) ? fptr(sensorHandle, enable) : false;
184 }
185 
186 WEAK_SYMBOL
chreSensorGetThreeAxisBias(uint32_t sensorHandle,struct chreSensorThreeAxisData * bias)187 bool chreSensorGetThreeAxisBias(uint32_t sensorHandle,
188                                 struct chreSensorThreeAxisData *bias) {
189   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorGetThreeAxisBias);
190   return (fptr != nullptr) ? fptr(sensorHandle, bias) : false;
191 }
192 
193 WEAK_SYMBOL
chreSensorFlushAsync(uint32_t sensorHandle,const void * cookie)194 bool chreSensorFlushAsync(uint32_t sensorHandle, const void *cookie) {
195   auto *fptr = CHRE_NSL_LAZY_LOOKUP(chreSensorFlushAsync);
196   return (fptr != nullptr) ? fptr(sensorHandle, cookie) : false;
197 }
198 
199 #endif  // CHRE_NANOAPP_DISABLE_BACKCOMPAT
200