blob: c91e67ab6408ee505fd6a51b4bef7a7575b1730d [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
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#define LOG_TAG "GnssHAL_GnssInterface"
18
19#include "Gnss.h"
20#include <GnssUtils.h>
21
22namespace android {
23namespace hardware {
24namespace gnss {
25namespace V1_0 {
26namespace implementation {
27
28#ifndef UNUSED
29#define UNUSED(x) (x)=(x)
30#endif
31
32std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
33sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
34bool Gnss::sInterfaceExists = false;
35bool Gnss::sWakelockHeldGnss = false;
36bool Gnss::sWakelockHeldFused = false;
37
38GpsCallbacks_ext Gnss::sGnssCb = {
39 .size = sizeof(GpsCallbacks_ext),
40 .location_cb = locationCb,
41 .status_cb = statusCb,
42 .sv_status_cb = gpsSvStatusCb,
43 .nmea_cb = nmeaCb,
44 .set_capabilities_cb = setCapabilitiesCb,
45 .acquire_wakelock_cb = acquireWakelockCb,
46 .release_wakelock_cb = releaseWakelockCb,
47 .create_thread_cb = createThreadCb,
48 .request_utc_time_cb = requestUtcTimeCb,
49 .set_system_info_cb = setSystemInfoCb,
50 .gnss_sv_status_cb = gnssSvStatusCb,
51
52 .set_name_cb = setNameCb,
53 .request_location_cb = requestLocationCb
54};
55
56uint32_t Gnss::sCapabilitiesCached = 0;
57uint16_t Gnss::sYearOfHwCached = 0;
58sem_t Gnss::sSem;
59
60Gnss::Gnss(gps_device_t_ext* gnssDevice) :
61 mDeathRecipient(new GnssHidlDeathRecipient(this)) {
62 /* Error out if an instance of the interface already exists. */
63 LOG_ALWAYS_FATAL_IF(sInterfaceExists);
64 sInterfaceExists = true;
65
66 if (gnssDevice == nullptr) {
67 ALOGE("%s: Invalid device_t handle", __func__);
68 return;
69 }
70
71 mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
72 sem_init(&sSem, 0, 1);
73}
74
75Gnss::~Gnss() {
76 sInterfaceExists = false;
77 sThreadFuncArgsList.clear();
78 sem_destroy(&sSem);
79}
80
81void Gnss::locationCb(GpsLocation_ext* location) {
82 sem_wait(&sSem);
83 if (sGnssCbIface == nullptr) {
84 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
85 sem_post(&sSem);
86 return;
87 }
88
89 if (location == nullptr) {
90 ALOGE("%s: Invalid location from GNSS HAL", __func__);
91 sem_post(&sSem);
92 return;
93 }
94
95 GnssLocation gnssLocation = V1_0::implementation::convertToGnssLocation(location);
96 auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
97 if (!ret.isOk()) {
98 ALOGE("%s: Unable to invoke callback", __func__);
99 }
100 sem_post(&sSem);
101}
102
103void Gnss::statusCb(GpsStatus* gnssStatus) {
104 sem_wait(&sSem);
105 if (sGnssCbIface == nullptr) {
106 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
107 sem_post(&sSem);
108 return;
109 }
110
111 if (gnssStatus == nullptr) {
112 ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
113 sem_post(&sSem);
114 return;
115 }
116
117 IGnssCallback::GnssStatusValue status =
118 static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
119
120 auto ret = sGnssCbIface->gnssStatusCb(status);
121 if (!ret.isOk()) {
122 ALOGE("%s: Unable to invoke callback", __func__);
123 }
124 sem_post(&sSem);
125}
126
127void Gnss::gnssSvStatusCb(GnssSvStatus_ext* status) {
128 sem_wait(&sSem);
129 if (sGnssCbIface == nullptr) {
130 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
131 sem_post(&sSem);
132 return;
133 }
134
135 if (status == nullptr) {
136 ALOGE("Invalid status from GNSS HAL %s", __func__);
137 sem_post(&sSem);
138 return;
139 }
140
141 IGnssCallback::GnssSvStatus svStatus;
142 svStatus.numSvs = status->num_svs;
143
144 if (svStatus.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
145 ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, V1_0::GnssMax::SVS_COUNT);
146 svStatus.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
147 }
148
149 for (size_t i = 0; i < svStatus.numSvs; i++) {
150 auto svInfo = status->gnss_sv_list[i];
151 IGnssCallback::GnssSvInfo gnssSvInfo = {
152 .svid = svInfo.legacySvInfo.svid,
153 .constellation = static_cast<V1_0::GnssConstellationType>(
154 svInfo.legacySvInfo.constellation),
155 .cN0Dbhz = svInfo.legacySvInfo.c_n0_dbhz,
156 .elevationDegrees = svInfo.legacySvInfo.elevation,
157 .azimuthDegrees = svInfo.legacySvInfo.azimuth,
158 .svFlag = static_cast<uint8_t>(svInfo.legacySvInfo.flags),
159 .carrierFrequencyHz = svInfo.carrier_frequency};
160 svStatus.gnssSvList[i] = gnssSvInfo;
161 }
162
163 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
164 if (!ret.isOk()) {
165 ALOGE("%s: Unable to invoke callback", __func__);
166 }
167 sem_post(&sSem);
168}
169
170/*
171 * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
172 * to GnssSvStatus for backward compatibility. It is only used by the default
173 * implementation and is not part of the GNSS interface.
174 */
175enum SvidValues : uint16_t {
176 GLONASS_SVID_OFFSET = 64,
177 GLONASS_SVID_COUNT = 24,
178 BEIDOU_SVID_OFFSET = 200,
179 BEIDOU_SVID_COUNT = 35,
180 SBAS_SVID_MIN = 33,
181 SBAS_SVID_MAX = 64,
182 SBAS_SVID_ADD = 87,
183 QZSS_SVID_MIN = 193,
184 QZSS_SVID_MAX = 200
185};
186
187/*
188 * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
189 * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
190 * being deprecated and is no longer part of the GNSS interface.
191 */
192void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
193 sem_wait(&sSem);
194 if (sGnssCbIface == nullptr) {
195 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
196 sem_post(&sSem);
197 return;
198 }
199
200 if (svInfo == nullptr) {
201 ALOGE("Invalid status from GNSS HAL %s", __func__);
202 sem_post(&sSem);
203 return;
204 }
205
206 IGnssCallback::GnssSvStatus svStatus;
207 svStatus.numSvs = svInfo->num_svs;
208 /*
209 * Clamp the list size since GnssSvStatus can support a maximum of
210 * GnssMax::SVS_COUNT entries.
211 */
212 ///M: fix max numSvs as GPS_MAX_SVS
213 if (svStatus.numSvs > static_cast<uint32_t>(GPS_MAX_SVS)) {
214 ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GPS_MAX_SVS);
215 svStatus.numSvs = static_cast<uint32_t>(GPS_MAX_SVS);
216 }
217 /// M: mtk update end
218
219 uint32_t ephemerisMask = svInfo->ephemeris_mask;
220 uint32_t almanacMask = svInfo->almanac_mask;
221 uint32_t usedInFixMask = svInfo->used_in_fix_mask;
222 /*
223 * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
224 */
225 for (size_t i = 0; i < svStatus.numSvs; i++) {
226 IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
227 info.svid = svInfo->sv_list[i].prn;
228 if (info.svid >= 1 && info.svid <= 32) {
229 info.constellation = GnssConstellationType::GPS;
230 } else if (info.svid > GLONASS_SVID_OFFSET &&
231 info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
232 info.constellation = GnssConstellationType::GLONASS;
233 info.svid -= GLONASS_SVID_OFFSET;
234 } else if (info.svid > BEIDOU_SVID_OFFSET &&
235 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
236 info.constellation = GnssConstellationType::BEIDOU;
237 info.svid -= BEIDOU_SVID_OFFSET;
238 } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
239 info.constellation = GnssConstellationType::SBAS;
240 info.svid += SBAS_SVID_ADD;
241 } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
242 info.constellation = GnssConstellationType::QZSS;
243 } else {
244 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
245 info.constellation = GnssConstellationType::UNKNOWN;
246 }
247
248 info.cN0Dbhz = svInfo->sv_list[i].snr;
249 info.elevationDegrees = svInfo->sv_list[i].elevation;
250 info.azimuthDegrees = svInfo->sv_list[i].azimuth;
251 // TODO: b/31702236
252 info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
253
254 /*
255 * Only GPS info is valid for these fields, as these masks are just 32
256 * bits, by GPS prn.
257 */
258 if (info.constellation == GnssConstellationType::GPS) {
259 int32_t svidMask = (1 << (info.svid - 1));
260 if ((ephemerisMask & svidMask) != 0) {
261 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
262 }
263 if ((almanacMask & svidMask) != 0) {
264 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
265 }
266 if ((usedInFixMask & svidMask) != 0) {
267 info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
268 }
269 }
270 }
271
272 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
273 if (!ret.isOk()) {
274 ALOGE("%s: Unable to invoke callback", __func__);
275 }
276 sem_post(&sSem);
277}
278
279void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
280 sem_wait(&sSem);
281 if (sGnssCbIface == nullptr) {
282 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
283 sem_post(&sSem);
284 return;
285 }
286
287 android::hardware::hidl_string nmeaString;
288 nmeaString.setToExternal(nmea, length);
289 auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
290 if (!ret.isOk()) {
291 ALOGE("%s: Unable to invoke callback", __func__);
292 }
293 sem_post(&sSem);
294}
295
296void Gnss::setCapabilitiesCb(uint32_t capabilities) {
297 sem_wait(&sSem);
298 if (sGnssCbIface == nullptr) {
299 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
300 sem_post(&sSem);
301 return;
302 }
303
304 auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
305 if (!ret.isOk()) {
306 ALOGE("%s: Unable to invoke callback", __func__);
307 }
308
309 // Save for reconnection when some legacy hal's don't resend this info
310 sCapabilitiesCached = capabilities;
311 sem_post(&sSem);
312}
313
314void Gnss::acquireWakelockCb() {
315 acquireWakelockGnss();
316}
317
318void Gnss::releaseWakelockCb() {
319 releaseWakelockGnss();
320}
321
322
323void Gnss::acquireWakelockGnss() {
324 sWakelockHeldGnss = true;
325 updateWakelock();
326}
327
328void Gnss::releaseWakelockGnss() {
329 sWakelockHeldGnss = false;
330 updateWakelock();
331}
332
333void Gnss::acquireWakelockFused() {
334 sWakelockHeldFused = true;
335 updateWakelock();
336}
337
338void Gnss::releaseWakelockFused() {
339 sWakelockHeldFused = false;
340 updateWakelock();
341}
342
343void Gnss::updateWakelock() {
344 // Track the state of the last request - in case the wake lock in the layer above is reference
345 // counted.
346 static bool sWakelockHeld = false;
347
348 sem_wait(&sSem);
349 if (sGnssCbIface == nullptr) {
350 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
351 sem_post(&sSem);
352 return;
353 }
354
355 if (sWakelockHeldGnss || sWakelockHeldFused) {
356 if (!sWakelockHeld) {
357 ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
358 sWakelockHeldGnss, sWakelockHeldFused);
359 sWakelockHeld = true;
360 auto ret = sGnssCbIface->gnssAcquireWakelockCb();
361 if (!ret.isOk()) {
362 ALOGE("%s: Unable to invoke callback", __func__);
363 }
364 }
365 } else {
366 if (sWakelockHeld) {
367 ALOGI("%s: GNSS HAL Wakelock released", __func__);
368 } else {
369 // To avoid burning power, always release, even if logic got here with sWakelock false
370 // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
371 ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
372 }
373 sWakelockHeld = false;
374 auto ret = sGnssCbIface->gnssReleaseWakelockCb();
375 if (!ret.isOk()) {
376 ALOGE("%s: Unable to invoke callback", __func__);
377 }
378 }
379 sem_post(&sSem);
380}
381
382void Gnss::requestUtcTimeCb() {
383 sem_wait(&sSem);
384 if (sGnssCbIface == nullptr) {
385 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
386 sem_post(&sSem);
387 return;
388 }
389
390 auto ret = sGnssCbIface->gnssRequestTimeCb();
391 if (!ret.isOk()) {
392 ALOGE("%s: Unable to invoke callback", __func__);
393 }
394 sem_post(&sSem);
395}
396
397pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
398 return createPthread(name, start, arg, &sThreadFuncArgsList);
399}
400
401void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
402 sem_wait(&sSem);
403 if (sGnssCbIface == nullptr) {
404 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
405 sem_post(&sSem);
406 return;
407 }
408
409 if (info == nullptr) {
410 ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
411 sem_post(&sSem);
412 return;
413 }
414
415 IGnssCallback::GnssSystemInfo gnssInfo = {
416 .yearOfHw = info->year_of_hw
417 };
418
419 auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
420 if (!ret.isOk()) {
421 ALOGE("%s: Unable to invoke callback", __func__);
422 }
423
424 // Save for reconnection when some legacy hal's don't resend this info
425 sYearOfHwCached = info->year_of_hw;
426 sem_post(&sSem);
427}
428
429void Gnss::setNameCb(const char* name, int length) {
430 UNUSED(name);
431 UNUSED(length);
432}
433
434void Gnss::requestLocationCb(bool independentFromGnss) {
435 UNUSED(independentFromGnss);
436}
437
438
439
440// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
441Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
442 if (mGnssIface == nullptr) {
443 ALOGE("%s: Gnss interface is unavailable", __func__);
444 return false;
445 }
446
447 if (callback == nullptr) {
448 ALOGE("%s: Null callback ignored", __func__);
449 return false;
450 }
451
452 sem_wait(&sSem);
453 if (sGnssCbIface != NULL) {
454 ALOGW("%s called more than once. Unexpected unless test.", __func__);
455 sGnssCbIface->unlinkToDeath(mDeathRecipient);
456 }
457
458 sGnssCbIface = callback;
459 callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
460 sem_post(&sSem);
461
462 // If this was received in the past, send it up again to refresh caller.
463 // mGnssIface will override after init() is called below, if needed
464 // (though it's unlikely the gps.h capabilities or system info will change.)
465 if (sCapabilitiesCached != 0) {
466 setCapabilitiesCb(sCapabilitiesCached);
467 }
468 if (sYearOfHwCached != 0) {
469 LegacyGnssSystemInfo info;
470 info.year_of_hw = sYearOfHwCached;
471 setSystemInfoCb(&info);
472 }
473
474 return (mGnssIface->init(&sGnssCb) == 0);
475}
476
477Return<bool> Gnss::start() {
478 if (mGnssIface == nullptr) {
479 ALOGE("%s: Gnss interface is unavailable", __func__);
480 return false;
481 }
482
483 return (mGnssIface->start() == 0);
484}
485
486Return<bool> Gnss::stop() {
487 if (mGnssIface == nullptr) {
488 ALOGE("%s: Gnss interface is unavailable", __func__);
489 return false;
490 }
491
492 return (mGnssIface->stop() == 0);
493}
494
495Return<void> Gnss::cleanup() {
496 if (mGnssIface == nullptr) {
497 ALOGE("%s: Gnss interface is unavailable", __func__);
498 } else {
499 mGnssIface->cleanup();
500 }
501 return Void();
502}
503
504Return<bool> Gnss::injectLocation(double latitudeDegrees,
505 double longitudeDegrees,
506 float accuracyMeters) {
507 if (mGnssIface == nullptr) {
508 ALOGE("%s: Gnss interface is unavailable", __func__);
509 return false;
510 }
511
512 return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
513}
514
515Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
516 int32_t uncertaintyMs) {
517 if (mGnssIface == nullptr) {
518 ALOGE("%s: Gnss interface is unavailable", __func__);
519 return false;
520 }
521
522 return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
523}
524
525Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags) {
526 if (mGnssIface == nullptr) {
527 ALOGE("%s: Gnss interface is unavailable", __func__);
528 } else {
529 mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
530 }
531 return Void();
532}
533
534Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
535 IGnss::GnssPositionRecurrence recurrence,
536 uint32_t minIntervalMs,
537 uint32_t preferredAccuracyMeters,
538 uint32_t preferredTimeMs) {
539 if (mGnssIface == nullptr) {
540 ALOGE("%s: Gnss interface is unavailable", __func__);
541 return false;
542 }
543
544 return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
545 static_cast<GpsPositionRecurrence>(recurrence),
546 minIntervalMs,
547 preferredAccuracyMeters,
548 preferredTimeMs,
549 false /* lowPowerMode*/) == 0);
550}
551
552Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() {
553 if (mGnssIface == nullptr) {
554 ALOGE("%s: Gnss interface is unavailable", __func__);
555 return nullptr;
556 }
557
558 if (mGnssRil == nullptr) {
559 const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
560 mGnssIface->get_extension(AGPS_RIL_INTERFACE));
561 if (agpsRilIface == nullptr) {
562 ALOGI("%s: GnssRil interface not implemented by HAL", __func__);
563 } else {
564 mGnssRil = new AGnssRil(agpsRilIface);
565 }
566 }
567 return mGnssRil;
568}
569
570Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
571 if (mGnssIface == nullptr) {
572 ALOGE("%s: Gnss interface is unavailable", __func__);
573 return nullptr;
574 }
575
576 /*if (mGnssConfig == nullptr) {
577 const GnssConfigurationInterface* gnssConfigIface =
578 static_cast<const GnssConfigurationInterface*>(
579 mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
580
581 if (gnssConfigIface == nullptr) {*/
582 ALOGW("%s: GnssConfiguration interface not implemented by HAL", __func__);
583 /*} else {
584 mGnssConfig = new GnssConfiguration(gnssConfigIface);
585 }
586 }*/
587 return mGnssConfig;
588}
589
590Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
591 if (mGnssIface == nullptr) {
592 ALOGE("%s: Gnss interface is unavailable", __func__);
593 return nullptr;
594 }
595
596 /*if (mGnssGeofencingIface == nullptr) {
597 const GpsGeofencingInterface* gpsGeofencingIface =
598 static_cast<const GpsGeofencingInterface*>(
599 mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
600
601 if (gpsGeofencingIface == nullptr) {*/
602 ALOGE("%s: GnssGeofencing interface not implemented by HAL", __func__);
603/* } else {
604 mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
605 }
606 }
607*/
608 return mGnssGeofencingIface;
609}
610
611Return<sp<IAGnss>> Gnss::getExtensionAGnss() {
612 if (mGnssIface == nullptr) {
613 ALOGE("%s: Gnss interface is unavailable", __func__);
614 return nullptr;
615 }
616
617 if (mAGnssIface == nullptr) {
618 const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
619 mGnssIface->get_extension(AGPS_INTERFACE));
620 if (agpsIface == nullptr) {
621 ALOGE("%s: AGnss interface not implemented by HAL", __func__);
622 } else {
623 mAGnssIface = new V1_0::implementation::AGnss(agpsIface);
624 }
625 }
626 return mAGnssIface;
627}
628
629Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
630 if (mGnssIface == nullptr) {
631 ALOGE("%s: Gnss interface is unavailable", __func__);
632 return nullptr;
633 }
634
635 if (mGnssNi == nullptr) {
636 const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
637 mGnssIface->get_extension(GPS_NI_INTERFACE));
638 if (gpsNiIface == nullptr) {
639 ALOGI("%s: GnssNi interface not implemented by HAL", __func__);
640 } else {
641 mGnssNi = new GnssNi(gpsNiIface);
642 }
643 }
644 return mGnssNi;
645}
646
647Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
648 if (mGnssIface == nullptr) {
649 ALOGE("%s: Gnss interface is unavailable", __func__);
650 return nullptr;
651 }
652
653 if (mGnssMeasurement == nullptr) {
654 const GpsMeasurementInterface_ext* gpsMeasurementIface =
655 static_cast<const GpsMeasurementInterface_ext*>(
656 mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
657
658 if (gpsMeasurementIface == nullptr) {
659 ALOGE("%s: GnssMeasurement interface not implemented by HAL", __func__);
660 } else {
661 mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
662 }
663 }
664 return mGnssMeasurement;
665}
666
667Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
668 if (mGnssIface == nullptr) {
669 ALOGE("%s: Gnss interface is unavailable", __func__);
670 return nullptr;
671 }
672
673 if (mGnssNavigationMessage == nullptr) {
674 const GpsNavigationMessageInterface* gpsNavigationMessageIface =
675 static_cast<const GpsNavigationMessageInterface*>(
676 mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
677
678 if (gpsNavigationMessageIface == nullptr) {
679 ALOGI("%s: GnssNavigationMessage interface not implemented by HAL", __func__);
680 } else {
681 mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
682 }
683 }
684
685 return mGnssNavigationMessage;
686}
687
688Return<sp<IGnssXtra>> Gnss::getExtensionXtra() {
689 if (mGnssIface == nullptr) {
690 ALOGE("%s: Gnss interface is unavailable", __func__);
691 return nullptr;
692 }
693
694 if (mGnssXtraIface == nullptr) {
695 const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
696 mGnssIface->get_extension(GPS_XTRA_INTERFACE));
697
698 if (gpsXtraIface == nullptr) {
699 ALOGI("%s: GnssXtra interface not implemented by HAL", __func__);
700 } else {
701 mGnssXtraIface = new GnssXtra(gpsXtraIface);
702 }
703 }
704
705 return mGnssXtraIface;
706}
707
708Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug() {
709 if (mGnssIface == nullptr) {
710 ALOGE("%s: Gnss interface is unavailable", __func__);
711 return nullptr;
712 }
713
714 if (mGnssDebug == nullptr) {
715 const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
716 mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
717
718 if (gpsDebugIface == nullptr) {
719 ALOGI("%s: GnssDebug interface not implemented by HAL", __func__);
720 } else {
721 mGnssDebug = new GnssDebug(gpsDebugIface);
722 }
723 }
724
725 return mGnssDebug;
726}
727
728Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() {
729 if (mGnssIface == nullptr) {
730 ALOGE("%s: Gnss interface is unavailable", __func__);
731 return nullptr;
732 }
733
734 if (mGnssBatching == nullptr) {
735 hw_module_t* module;
736 const FlpLocationInterface* flpLocationIface = nullptr;
737 int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
738
739 if (err != 0) {
740 ALOGE("gnss flp hw_get_module failed: %d", err);
741 } else if (module == nullptr) {
742 ALOGE("Fused Location hw_get_module returned null module");
743 } else if (module->methods == nullptr) {
744 ALOGE("Fused Location hw_get_module returned null methods");
745 } else {
746 hw_device_t* device;
747 err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
748 if (err != 0) {
749 ALOGE("flpDevice open failed: %d", err);
750 } else {
751 flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
752 flpLocationIface = flpDevice->get_flp_interface(flpDevice);
753 }
754 }
755
756 if (flpLocationIface == nullptr) {
757 ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
758 } else {
759 mGnssBatching = new GnssBatching(flpLocationIface);
760 }
761 }
762 return mGnssBatching;
763}
764
765void Gnss::handleHidlDeath() {
766 ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
767
768 /// M: move here! Do not callback to system_server to avoid gnss hidl service NE
769 /*
770 * This has died, so close it off in case (race condition) callbacks happen
771 * before HAL processes above messages.
772 */
773 sem_wait(&sSem);
774 sGnssCbIface = nullptr;
775 sem_post(&sSem);
776
777 // commands down to the HAL implementation
778 stop(); // stop ongoing GPS tracking
779 if (mGnssMeasurement != nullptr) {
780 mGnssMeasurement->close();
781 }
782 if (mGnssNavigationMessage != nullptr) {
783 mGnssNavigationMessage->close();
784 }
785 if (mGnssBatching != nullptr) {
786 mGnssBatching->stop();
787 mGnssBatching->cleanup();
788 }
789 cleanup();
790
791}
792
793IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
794 hw_module_t* module;
795 IGnss* iface = nullptr;
796 int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
797
798 if (err == 0) {
799 hw_device_t* device;
800 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
801 if (err == 0) {
802 iface = new Gnss(reinterpret_cast<gps_device_t_ext*>(device));
803 } else {
804 ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
805 }
806 } else {
807 ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
808 }
809 return iface;
810}
811
812} // namespace implementation
813} // namespace V1_0
814} // namespace gnss
815} // namespace hardware
816} // namespace android