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