1 /*
2 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
3 * Not a Contribution
4 */
5 /*
6 * Copyright (C) 2016 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #define LOG_TAG "LocSvc_GnssInterface"
22
23 #include <fstream>
24 #include <log_util.h>
25 #include <dlfcn.h>
26 #include <cutils/properties.h>
27 #include "Gnss.h"
28 #include <LocationUtil.h>
29
30 typedef void* (getLocationInterface)();
31
32 #define IMAGES_INFO_FILE "/sys/devices/soc0/images"
33 #define DELIMITER ";"
34
35 namespace android {
36 namespace hardware {
37 namespace gnss {
38 namespace V1_1 {
39 namespace implementation {
40
getVersionString()41 static std::string getVersionString() {
42 static std::string version;
43 if (!version.empty())
44 return version;
45
46 char value[PROPERTY_VALUE_MAX] = {0};
47 property_get("ro.hardware", value, "unknown");
48 version.append(value).append(DELIMITER);
49
50 std::ifstream in(IMAGES_INFO_FILE);
51 std::string s;
52 while(getline(in, s)) {
53 std::size_t found = s.find("CRM:");
54 if (std::string::npos == found) {
55 continue;
56 }
57
58 // skip over space characters after "CRM:"
59 const char* substr = s.c_str();
60 found += 4;
61 while (0 != substr[found] && isspace(substr[found])) {
62 found++;
63 }
64 if (s.find("11:") != found) {
65 continue;
66 }
67 s.erase(0, found + 3);
68
69 found = s.find_first_of("\r\n");
70 if (std::string::npos != found) {
71 s.erase(s.begin() + found, s.end());
72 }
73 version.append(s).append(DELIMITER);
74 }
75 return version;
76 }
77
serviceDied(uint64_t cookie,const wp<IBase> & who)78 void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
79 LOC_LOGE("%s] service died. cookie: %llu, who: %p",
80 __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
81 if (mGnss != nullptr) {
82 mGnss->stop();
83 mGnss->cleanup();
84 }
85 }
86
Gnss()87 Gnss::Gnss() {
88 ENTRY_LOG_CALLFLOW();
89 // clear pending GnssConfig
90 memset(&mPendingConfig, 0, sizeof(GnssConfig));
91
92 mGnssDeathRecipient = new GnssDeathRecipient(this);
93 }
94
~Gnss()95 Gnss::~Gnss() {
96 ENTRY_LOG_CALLFLOW();
97 if (mApi != nullptr) {
98 delete mApi;
99 mApi = nullptr;
100 }
101 }
102
getApi()103 GnssAPIClient* Gnss::getApi() {
104 if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
105 mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
106 if (mApi == nullptr) {
107 LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
108 return mApi;
109 }
110
111 if (mPendingConfig.size == sizeof(GnssConfig)) {
112 // we have pending GnssConfig
113 mApi->gnssConfigurationUpdate(mPendingConfig);
114 // clear size to invalid mPendingConfig
115 mPendingConfig.size = 0;
116 if (mPendingConfig.assistanceServer.hostName != nullptr) {
117 free((void*)mPendingConfig.assistanceServer.hostName);
118 }
119 }
120 }
121 if (mApi == nullptr) {
122 LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
123 }
124 return mApi;
125 }
126
getGnssInterface()127 GnssInterface* Gnss::getGnssInterface() {
128 static bool getGnssInterfaceFailed = false;
129 if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
130 LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__);
131 getLocationInterface* getter = NULL;
132 const char *error = NULL;
133 dlerror();
134 void *handle = dlopen("libgnss.so", RTLD_NOW);
135 if (NULL == handle || (error = dlerror()) != NULL) {
136 LOC_LOGW("dlopen for libgnss.so failed, error = %s", error);
137 } else {
138 getter = (getLocationInterface*)dlsym(handle, "getGnssInterface");
139 if ((error = dlerror()) != NULL) {
140 LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error);
141 getter = NULL;
142 }
143 }
144
145 if (NULL == getter) {
146 getGnssInterfaceFailed = true;
147 } else {
148 mGnssInterface = (GnssInterface*)(*getter)();
149 }
150 }
151 return mGnssInterface;
152 }
153
setCallback(const sp<V1_0::IGnssCallback> & callback)154 Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
155 ENTRY_LOG_CALLFLOW();
156 if (mGnssCbIface != nullptr) {
157 mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
158 }
159 mGnssCbIface = callback;
160 if (mGnssCbIface != nullptr) {
161 mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
162 }
163
164 GnssAPIClient* api = getApi();
165 if (api != nullptr) {
166 api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
167 api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
168 api->requestCapabilities();
169 }
170 return true;
171 }
172
setGnssNiCb(const sp<IGnssNiCallback> & callback)173 Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
174 ENTRY_LOG_CALLFLOW();
175 mGnssNiCbIface = callback;
176 GnssAPIClient* api = getApi();
177 if (api != nullptr) {
178 api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
179 }
180 return true;
181 }
182
updateConfiguration(GnssConfig & gnssConfig)183 Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
184 ENTRY_LOG_CALLFLOW();
185 GnssAPIClient* api = getApi();
186 if (api) {
187 api->gnssConfigurationUpdate(gnssConfig);
188 } else if (gnssConfig.flags != 0) {
189 // api is not ready yet, update mPendingConfig with gnssConfig
190 mPendingConfig.size = sizeof(GnssConfig);
191
192 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
193 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
194 mPendingConfig.gpsLock = gnssConfig.gpsLock;
195 }
196 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
197 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
198 mPendingConfig.suplVersion = gnssConfig.suplVersion;
199 }
200 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
201 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
202 mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
203 mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
204 if (mPendingConfig.assistanceServer.hostName != nullptr) {
205 free((void*)mPendingConfig.assistanceServer.hostName);
206 mPendingConfig.assistanceServer.hostName =
207 strdup(gnssConfig.assistanceServer.hostName);
208 }
209 mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
210 }
211 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
212 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
213 mPendingConfig.lppProfile = gnssConfig.lppProfile;
214 }
215 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
216 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
217 mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
218 }
219 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
220 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
221 mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
222 }
223 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
224 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
225 mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
226 }
227 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
228 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
229 mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
230 }
231 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
232 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
233 mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
234 }
235 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
236 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
237 mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
238 }
239 if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
240 mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
241 mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
242 }
243 }
244 return true;
245 }
246
start()247 Return<bool> Gnss::start() {
248 ENTRY_LOG_CALLFLOW();
249 bool retVal = false;
250 GnssAPIClient* api = getApi();
251 if (api) {
252 retVal = api->gnssStart();
253 }
254 return retVal;
255 }
256
stop()257 Return<bool> Gnss::stop() {
258 ENTRY_LOG_CALLFLOW();
259 bool retVal = false;
260 GnssAPIClient* api = getApi();
261 if (api) {
262 retVal = api->gnssStop();
263 }
264 return retVal;
265 }
266
cleanup()267 Return<void> Gnss::cleanup() {
268 ENTRY_LOG_CALLFLOW();
269
270 if (mApi != nullptr) {
271 mApi->gnssDisable();
272 }
273
274 return Void();
275 }
276
injectLocation(double latitudeDegrees,double longitudeDegrees,float accuracyMeters)277 Return<bool> Gnss::injectLocation(double latitudeDegrees,
278 double longitudeDegrees,
279 float accuracyMeters) {
280 ENTRY_LOG_CALLFLOW();
281 GnssInterface* gnssInterface = getGnssInterface();
282 if (nullptr != gnssInterface) {
283 gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
284 return true;
285 } else {
286 return false;
287 }
288 }
289
injectTime(int64_t timeMs,int64_t timeReferenceMs,int32_t uncertaintyMs)290 Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
291 int32_t uncertaintyMs) {
292 ENTRY_LOG_CALLFLOW();
293 GnssInterface* gnssInterface = getGnssInterface();
294 if (nullptr != gnssInterface) {
295 gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs);
296 return true;
297 } else {
298 return false;
299 }
300 }
301
deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags)302 Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
303 ENTRY_LOG_CALLFLOW();
304 GnssAPIClient* api = getApi();
305 if (api) {
306 api->gnssDeleteAidingData(aidingDataFlags);
307 }
308 return Void();
309 }
310
setPositionMode(V1_0::IGnss::GnssPositionMode mode,V1_0::IGnss::GnssPositionRecurrence recurrence,uint32_t minIntervalMs,uint32_t preferredAccuracyMeters,uint32_t preferredTimeMs)311 Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
312 V1_0::IGnss::GnssPositionRecurrence recurrence,
313 uint32_t minIntervalMs,
314 uint32_t preferredAccuracyMeters,
315 uint32_t preferredTimeMs) {
316 ENTRY_LOG_CALLFLOW();
317 bool retVal = false;
318 GnssAPIClient* api = getApi();
319 if (api) {
320 retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
321 preferredAccuracyMeters, preferredTimeMs);
322 }
323 return retVal;
324 }
325
getExtensionAGnss()326 Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
327 ENTRY_LOG_CALLFLOW();
328 mAGnssIface = new AGnss(this);
329 return mAGnssIface;
330 }
331
getExtensionGnssNi()332 Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
333 ENTRY_LOG_CALLFLOW();
334 mGnssNi = new GnssNi(this);
335 return mGnssNi;
336 }
337
getExtensionGnssMeasurement()338 Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
339 ENTRY_LOG_CALLFLOW();
340 if (mGnssMeasurement == nullptr)
341 mGnssMeasurement = new GnssMeasurement();
342 return mGnssMeasurement;
343 }
344
getExtensionGnssConfiguration()345 Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
346 ENTRY_LOG_CALLFLOW();
347 mGnssConfig = new GnssConfiguration(this);
348 return mGnssConfig;
349 }
350
getExtensionGnssGeofencing()351 Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
352 ENTRY_LOG_CALLFLOW();
353 mGnssGeofencingIface = new GnssGeofencing();
354 return mGnssGeofencingIface;
355 }
356
getExtensionGnssBatching()357 Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
358 mGnssBatching = new GnssBatching();
359 return mGnssBatching;
360 }
361
getExtensionGnssDebug()362 Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
363 ENTRY_LOG_CALLFLOW();
364 mGnssDebug = new GnssDebug(this);
365 return mGnssDebug;
366 }
367
getExtensionAGnssRil()368 Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
369 mGnssRil = new AGnssRil(this);
370 return mGnssRil;
371 }
372
373 // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
setCallback_1_1(const sp<V1_1::IGnssCallback> & callback)374 Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
375 ENTRY_LOG_CALLFLOW();
376 callback->gnssNameCb(getVersionString());
377 mGnssCbIface_1_1 = callback;
378 GnssInterface* gnssInterface = getGnssInterface();
379 if (nullptr != gnssInterface) {
380 OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
381 odcpiRequestCb(odcpiRequest);
382 };
383 gnssInterface->odcpiInit(cb);
384 }
385 return setCallback(callback);
386 }
387
setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,V1_0::IGnss::GnssPositionRecurrence recurrence,uint32_t minIntervalMs,uint32_t preferredAccuracyMeters,uint32_t preferredTimeMs,bool lowPowerMode)388 Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
389 V1_0::IGnss::GnssPositionRecurrence recurrence,
390 uint32_t minIntervalMs,
391 uint32_t preferredAccuracyMeters,
392 uint32_t preferredTimeMs,
393 bool lowPowerMode) {
394 ENTRY_LOG_CALLFLOW();
395 bool retVal = false;
396 GnssAPIClient* api = getApi();
397 if (api) {
398 GnssPowerMode powerMode = lowPowerMode?
399 GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
400 retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
401 preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
402 }
403 return retVal;
404 }
405
getExtensionGnssMeasurement_1_1()406 Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
407 ENTRY_LOG_CALLFLOW();
408 if (mGnssMeasurement == nullptr)
409 mGnssMeasurement = new GnssMeasurement();
410 return mGnssMeasurement;
411 }
412
getExtensionGnssConfiguration_1_1()413 Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
414 ENTRY_LOG_CALLFLOW();
415 if (mGnssConfig == nullptr)
416 mGnssConfig = new GnssConfiguration(this);
417 return mGnssConfig;
418 }
419
injectBestLocation(const GnssLocation & gnssLocation)420 Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
421 ENTRY_LOG_CALLFLOW();
422 GnssInterface* gnssInterface = getGnssInterface();
423 if (nullptr != gnssInterface) {
424 Location location = {};
425 convertGnssLocation(gnssLocation, location);
426 gnssInterface->odcpiInject(location);
427 }
428 return true;
429 }
430
odcpiRequestCb(const OdcpiRequestInfo & request)431 void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
432 ENTRY_LOG_CALLFLOW();
433 if (mGnssCbIface_1_1 != nullptr) {
434 // For emergency mode, request DBH (Device based hybrid) location
435 // Mark Independent from GNSS flag to false.
436 if (ODCPI_REQUEST_TYPE_START == request.type) {
437 auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
438 if (!r.isOk()) {
439 LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
440 }
441 } else {
442 LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
443 }
444 } else {
445 LOC_LOGe("ODCPI request not supported.");
446 }
447 }
448
HIDL_FETCH_IGnss(const char * hal)449 IGnss* HIDL_FETCH_IGnss(const char* hal) {
450 ENTRY_LOG_CALLFLOW();
451 IGnss* iface = nullptr;
452 iface = new Gnss();
453 if (iface == nullptr) {
454 LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
455 }
456 return iface;
457 }
458
459 } // namespace implementation
460 } // namespace V1_1
461 } // namespace gnss
462 } // namespace hardware
463 } // namespace android
464