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