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