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