blob: cfcee243bb7c389cc474f0da6baaf15328c73049 [file] [log] [blame]
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -07001/*
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
28std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
29sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
30bool Gnss::sInterfaceExists = false;
Wyatt Riley8791e7b2017-01-17 12:12:25 -080031bool Gnss::sWakelockHeldGnss = false;
32bool Gnss::sWakelockHeldFused = false;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070033
34GpsCallbacks Gnss::sGnssCb = {
35 .size = sizeof(GpsCallbacks),
36 .location_cb = locationCb,
37 .status_cb = statusCb,
38 .sv_status_cb = gpsSvStatusCb,
39 .nmea_cb = nmeaCb,
40 .set_capabilities_cb = setCapabilitiesCb,
41 .acquire_wakelock_cb = acquireWakelockCb,
42 .release_wakelock_cb = releaseWakelockCb,
43 .create_thread_cb = createThreadCb,
44 .request_utc_time_cb = requestUtcTimeCb,
45 .set_system_info_cb = setSystemInfoCb,
46 .gnss_sv_status_cb = gnssSvStatusCb,
47};
48
Wyatt Riley917640b2017-03-16 16:25:55 -070049uint32_t Gnss::sCapabilitiesCached = 0;
50uint16_t Gnss::sYearOfHwCached = 0;
51
52Gnss::Gnss(gps_device_t* gnssDevice) :
53 mDeathRecipient(new GnssHidlDeathRecipient(this)) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070054 /* Error out if an instance of the interface already exists. */
55 LOG_ALWAYS_FATAL_IF(sInterfaceExists);
56 sInterfaceExists = true;
57
58 if (gnssDevice == nullptr) {
59 ALOGE("%s: Invalid device_t handle", __func__);
60 return;
61 }
62
63 mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
64}
65
66Gnss::~Gnss() {
Hridya Valsarajue020ce22017-02-15 20:31:18 -080067 sInterfaceExists = false;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070068 sThreadFuncArgsList.clear();
69}
70
71void Gnss::locationCb(GpsLocation* location) {
72 if (sGnssCbIface == nullptr) {
73 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
74 return;
75 }
76
77 if (location == nullptr) {
78 ALOGE("%s: Invalid location from GNSS HAL", __func__);
79 return;
80 }
81
82 android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
Hridya Valsarajue020ce22017-02-15 20:31:18 -080083 auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
84 if (!ret.isOk()) {
85 ALOGE("%s: Unable to invoke callback", __func__);
86 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070087}
88
89void Gnss::statusCb(GpsStatus* gnssStatus) {
90 if (sGnssCbIface == nullptr) {
91 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
92 return;
93 }
94
95 if (gnssStatus == nullptr) {
96 ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
97 return;
98 }
99
100 IGnssCallback::GnssStatusValue status =
101 static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
102
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800103 auto ret = sGnssCbIface->gnssStatusCb(status);
104 if (!ret.isOk()) {
105 ALOGE("%s: Unable to invoke callback", __func__);
106 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700107}
108
109void Gnss::gnssSvStatusCb(GnssSvStatus* status) {
110 if (sGnssCbIface == nullptr) {
111 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
112 return;
113 }
114
115 if (status == nullptr) {
116 ALOGE("Invalid status from GNSS HAL %s", __func__);
117 return;
118 }
119
120 IGnssCallback::GnssSvStatus svStatus;
121 svStatus.numSvs = status->num_svs;
122
123 if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
124 ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
125 svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
126 }
127
128 for (size_t i = 0; i < svStatus.numSvs; i++) {
129 auto svInfo = status->gnss_sv_list[i];
130 IGnssCallback::GnssSvInfo gnssSvInfo = {
131 .svid = svInfo.svid,
Yipeng Caoa36f51a2017-04-27 18:29:25 -0700132 .constellation = static_cast<
133 android::hardware::gnss::V1_0::GnssConstellationType>(
134 svInfo.constellation),
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700135 .cN0Dbhz = svInfo.c_n0_dbhz,
136 .elevationDegrees = svInfo.elevation,
137 .azimuthDegrees = svInfo.azimuth,
Yipeng Caoa36f51a2017-04-27 18:29:25 -0700138 // Older chipsets do not provide carrier frequency, hence
139 // HAS_CARRIER_FREQUENCY flag and the carrierFrequencyHz fields
140 // are not set. So we are resetting both fields here.
141 .svFlag = static_cast<uint8_t>(
142 svInfo.flags &= ~(static_cast<uint8_t>(
143 IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY))),
144 .carrierFrequencyHz = 0};
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700145 svStatus.gnssSvList[i] = gnssSvInfo;
146 }
147
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800148 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
149 if (!ret.isOk()) {
150 ALOGE("%s: Unable to invoke callback", __func__);
151 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700152}
153
154/*
155 * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
156 * to GnssSvStatus for backward compatibility. It is only used by the default
157 * implementation and is not part of the GNSS interface.
158 */
159enum SvidValues : uint16_t {
160 GLONASS_SVID_OFFSET = 64,
161 GLONASS_SVID_COUNT = 24,
162 BEIDOU_SVID_OFFSET = 200,
163 BEIDOU_SVID_COUNT = 35,
164 SBAS_SVID_MIN = 33,
165 SBAS_SVID_MAX = 64,
166 SBAS_SVID_ADD = 87,
167 QZSS_SVID_MIN = 193,
168 QZSS_SVID_MAX = 200
169};
170
171/*
172 * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
173 * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
174 * being deprecated and is no longer part of the GNSS interface.
175 */
176void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
177 if (sGnssCbIface == nullptr) {
178 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
179 return;
180 }
181
182 if (svInfo == nullptr) {
183 ALOGE("Invalid status from GNSS HAL %s", __func__);
184 return;
185 }
186
187 IGnssCallback::GnssSvStatus svStatus;
188 svStatus.numSvs = svInfo->num_svs;
189 /*
190 * Clamp the list size since GnssSvStatus can support a maximum of
191 * GnssMax::SVS_COUNT entries.
192 */
193 if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
194 ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
195 svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
196 }
197
198 uint32_t ephemerisMask = svInfo->ephemeris_mask;
199 uint32_t almanacMask = svInfo->almanac_mask;
200 uint32_t usedInFixMask = svInfo->used_in_fix_mask;
201 /*
202 * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
203 */
204 for (size_t i = 0; i < svStatus.numSvs; i++) {
205 IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
206 info.svid = svInfo->sv_list[i].prn;
207 if (info.svid >= 1 && info.svid <= 32) {
208 info.constellation = GnssConstellationType::GPS;
209 } else if (info.svid > GLONASS_SVID_OFFSET &&
210 info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
211 info.constellation = GnssConstellationType::GLONASS;
212 info.svid -= GLONASS_SVID_OFFSET;
213 } else if (info.svid > BEIDOU_SVID_OFFSET &&
214 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
215 info.constellation = GnssConstellationType::BEIDOU;
216 info.svid -= BEIDOU_SVID_OFFSET;
217 } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
218 info.constellation = GnssConstellationType::SBAS;
219 info.svid += SBAS_SVID_ADD;
220 } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
221 info.constellation = GnssConstellationType::QZSS;
222 } else {
223 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
224 info.constellation = GnssConstellationType::UNKNOWN;
225 }
226
227 info.cN0Dbhz = svInfo->sv_list[i].snr;
228 info.elevationDegrees = svInfo->sv_list[i].elevation;
229 info.azimuthDegrees = svInfo->sv_list[i].azimuth;
Yifan Hong35e2aac2016-12-05 12:35:05 -0800230 // TODO: b/31702236
231 info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700232
233 /*
234 * Only GPS info is valid for these fields, as these masks are just 32
235 * bits, by GPS prn.
236 */
237 if (info.constellation == GnssConstellationType::GPS) {
238 int32_t svidMask = (1 << (info.svid - 1));
239 if ((ephemerisMask & svidMask) != 0) {
240 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
241 }
242 if ((almanacMask & svidMask) != 0) {
243 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
244 }
245 if ((usedInFixMask & svidMask) != 0) {
246 info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
247 }
248 }
249 }
250
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800251 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
252 if (!ret.isOk()) {
253 ALOGE("%s: Unable to invoke callback", __func__);
254 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700255}
256
257void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
258 if (sGnssCbIface == nullptr) {
259 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
260 return;
261 }
262
263 android::hardware::hidl_string nmeaString;
264 nmeaString.setToExternal(nmea, length);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800265 auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
266 if (!ret.isOk()) {
267 ALOGE("%s: Unable to invoke callback", __func__);
268 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700269}
270
271void Gnss::setCapabilitiesCb(uint32_t capabilities) {
272 if (sGnssCbIface == nullptr) {
273 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
274 return;
275 }
276
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800277 auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
278 if (!ret.isOk()) {
279 ALOGE("%s: Unable to invoke callback", __func__);
280 }
Wyatt Riley917640b2017-03-16 16:25:55 -0700281
282 // Save for reconnection when some legacy hal's don't resend this info
283 sCapabilitiesCached = capabilities;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700284}
285
286void Gnss::acquireWakelockCb() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800287 acquireWakelockGnss();
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700288}
289
290void Gnss::releaseWakelockCb() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800291 releaseWakelockGnss();
292}
293
294
295void Gnss::acquireWakelockGnss() {
296 sWakelockHeldGnss = true;
297 updateWakelock();
298}
299
300void Gnss::releaseWakelockGnss() {
301 sWakelockHeldGnss = false;
302 updateWakelock();
303}
304
305void Gnss::acquireWakelockFused() {
306 sWakelockHeldFused = true;
307 updateWakelock();
308}
309
310void Gnss::releaseWakelockFused() {
311 sWakelockHeldFused = false;
312 updateWakelock();
313}
314
315void Gnss::updateWakelock() {
316 // Track the state of the last request - in case the wake lock in the layer above is reference
317 // counted.
318 static bool sWakelockHeld = false;
319
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700320 if (sGnssCbIface == nullptr) {
321 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
322 return;
323 }
324
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800325 if (sWakelockHeldGnss || sWakelockHeldFused) {
326 if (!sWakelockHeld) {
327 ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
328 sWakelockHeldGnss, sWakelockHeldFused);
329 sWakelockHeld = true;
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800330 auto ret = sGnssCbIface->gnssAcquireWakelockCb();
331 if (!ret.isOk()) {
332 ALOGE("%s: Unable to invoke callback", __func__);
333 }
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800334 }
335 } else {
336 if (sWakelockHeld) {
337 ALOGI("%s: GNSS HAL Wakelock released", __func__);
338 } else {
339 // To avoid burning power, always release, even if logic got here with sWakelock false
340 // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
341 ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
342 }
343 sWakelockHeld = false;
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800344 auto ret = sGnssCbIface->gnssReleaseWakelockCb();
345 if (!ret.isOk()) {
346 ALOGE("%s: Unable to invoke callback", __func__);
347 }
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800348 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700349}
350
351void Gnss::requestUtcTimeCb() {
352 if (sGnssCbIface == nullptr) {
353 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
354 return;
355 }
356
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800357 auto ret = sGnssCbIface->gnssRequestTimeCb();
358 if (!ret.isOk()) {
359 ALOGE("%s: Unable to invoke callback", __func__);
360 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700361}
362
363pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
364 return createPthread(name, start, arg, &sThreadFuncArgsList);
365}
366
367void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
368 if (sGnssCbIface == nullptr) {
369 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
370 return;
371 }
372
373 if (info == nullptr) {
374 ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
375 return;
376 }
377
378 IGnssCallback::GnssSystemInfo gnssInfo = {
379 .yearOfHw = info->year_of_hw
380 };
381
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800382 auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
383 if (!ret.isOk()) {
384 ALOGE("%s: Unable to invoke callback", __func__);
385 }
Wyatt Riley917640b2017-03-16 16:25:55 -0700386
387 // Save for reconnection when some legacy hal's don't resend this info
388 sYearOfHwCached = info->year_of_hw;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700389}
390
391
392// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
393Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
394 if (mGnssIface == nullptr) {
395 ALOGE("%s: Gnss interface is unavailable", __func__);
396 return false;
397 }
398
Wyatt Riley917640b2017-03-16 16:25:55 -0700399 if (callback == nullptr) {
400 ALOGE("%s: Null callback ignored", __func__);
401 return false;
402 }
403
404 if (sGnssCbIface != NULL) {
405 ALOGW("%s called more than once. Unexpected unless test.", __func__);
406 sGnssCbIface->unlinkToDeath(mDeathRecipient);
407 }
408
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700409 sGnssCbIface = callback;
Wyatt Riley917640b2017-03-16 16:25:55 -0700410 callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
411
412 // If this was received in the past, send it up again to refresh caller.
413 // mGnssIface will override after init() is called below, if needed
414 // (though it's unlikely the gps.h capabilities or system info will change.)
415 if (sCapabilitiesCached != 0) {
416 setCapabilitiesCb(sCapabilitiesCached);
417 }
418 if (sYearOfHwCached != 0) {
419 LegacyGnssSystemInfo info;
420 info.year_of_hw = sYearOfHwCached;
421 setSystemInfoCb(&info);
422 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700423
424 return (mGnssIface->init(&sGnssCb) == 0);
425}
426
427Return<bool> Gnss::start() {
428 if (mGnssIface == nullptr) {
429 ALOGE("%s: Gnss interface is unavailable", __func__);
430 return false;
431 }
432
433 return (mGnssIface->start() == 0);
434}
435
436Return<bool> Gnss::stop() {
437 if (mGnssIface == nullptr) {
438 ALOGE("%s: Gnss interface is unavailable", __func__);
439 return false;
440 }
441
442 return (mGnssIface->stop() == 0);
443}
444
445Return<void> Gnss::cleanup() {
446 if (mGnssIface == nullptr) {
447 ALOGE("%s: Gnss interface is unavailable", __func__);
448 } else {
449 mGnssIface->cleanup();
450 }
451 return Void();
452}
453
454Return<bool> Gnss::injectLocation(double latitudeDegrees,
455 double longitudeDegrees,
456 float accuracyMeters) {
457 if (mGnssIface == nullptr) {
458 ALOGE("%s: Gnss interface is unavailable", __func__);
459 return false;
460 }
461
462 return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
463}
464
465Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
466 int32_t uncertaintyMs) {
467 if (mGnssIface == nullptr) {
468 ALOGE("%s: Gnss interface is unavailable", __func__);
469 return false;
470 }
471
472 return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
473}
474
475Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags) {
476 if (mGnssIface == nullptr) {
477 ALOGE("%s: Gnss interface is unavailable", __func__);
478 } else {
479 mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
480 }
481 return Void();
482}
483
484Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
485 IGnss::GnssPositionRecurrence recurrence,
486 uint32_t minIntervalMs,
487 uint32_t preferredAccuracyMeters,
488 uint32_t preferredTimeMs) {
489 if (mGnssIface == nullptr) {
490 ALOGE("%s: Gnss interface is unavailable", __func__);
491 return false;
492 }
493
494 return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
495 static_cast<GpsPositionRecurrence>(recurrence),
496 minIntervalMs,
497 preferredAccuracyMeters,
498 preferredTimeMs) == 0);
499}
500
Martijn Coenen527924a2017-01-04 12:59:48 +0100501Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700502 if (mGnssIface == nullptr) {
503 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800504 return nullptr;
505 }
506
507 if (mGnssRil == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700508 const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
509 mGnssIface->get_extension(AGPS_RIL_INTERFACE));
510 if (agpsRilIface == nullptr) {
511 ALOGE("%s GnssRil interface not implemented by GNSS HAL", __func__);
512 } else {
513 mGnssRil = new AGnssRil(agpsRilIface);
514 }
515 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100516 return mGnssRil;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700517}
518
Martijn Coenen527924a2017-01-04 12:59:48 +0100519Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700520 if (mGnssIface == nullptr) {
521 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800522 return nullptr;
523 }
524
525 if (mGnssConfig == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700526 const GnssConfigurationInterface* gnssConfigIface =
527 static_cast<const GnssConfigurationInterface*>(
528 mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
529
530 if (gnssConfigIface == nullptr) {
531 ALOGE("%s GnssConfiguration interface not implemented by GNSS HAL", __func__);
532 } else {
533 mGnssConfig = new GnssConfiguration(gnssConfigIface);
534 }
535 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100536 return mGnssConfig;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700537}
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800538
Martijn Coenen527924a2017-01-04 12:59:48 +0100539Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700540 if (mGnssIface == nullptr) {
541 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800542 return nullptr;
543 }
544
545 if (mGnssGeofencingIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700546 const GpsGeofencingInterface* gpsGeofencingIface =
547 static_cast<const GpsGeofencingInterface*>(
548 mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
549
550 if (gpsGeofencingIface == nullptr) {
551 ALOGE("%s GnssGeofencing interface not implemented by GNSS HAL", __func__);
552 } else {
553 mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
554 }
555 }
556
Martijn Coenen527924a2017-01-04 12:59:48 +0100557 return mGnssGeofencingIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700558}
559
Martijn Coenen527924a2017-01-04 12:59:48 +0100560Return<sp<IAGnss>> Gnss::getExtensionAGnss() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700561 if (mGnssIface == nullptr) {
562 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800563 return nullptr;
564 }
565
566 if (mAGnssIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700567 const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
568 mGnssIface->get_extension(AGPS_INTERFACE));
569 if (agpsIface == nullptr) {
570 ALOGE("%s AGnss interface not implemented by GNSS HAL", __func__);
571 } else {
572 mAGnssIface = new AGnss(agpsIface);
573 }
574 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100575 return mAGnssIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700576}
577
Martijn Coenen527924a2017-01-04 12:59:48 +0100578Return<sp<IGnssNi>> Gnss::getExtensionGnssNi() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700579 if (mGnssIface == nullptr) {
580 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800581 return nullptr;
582 }
583
584 if (mGnssNi == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700585 const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
586 mGnssIface->get_extension(GPS_NI_INTERFACE));
587 if (gpsNiIface == nullptr) {
588 ALOGE("%s GnssNi interface not implemented by GNSS HAL", __func__);
589 } else {
590 mGnssNi = new GnssNi(gpsNiIface);
591 }
592 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100593 return mGnssNi;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700594}
595
Martijn Coenen527924a2017-01-04 12:59:48 +0100596Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700597 if (mGnssIface == nullptr) {
598 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800599 return nullptr;
600 }
601
602 if (mGnssMeasurement == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700603 const GpsMeasurementInterface* gpsMeasurementIface =
604 static_cast<const GpsMeasurementInterface*>(
605 mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
606
607 if (gpsMeasurementIface == nullptr) {
608 ALOGE("%s GnssMeasurement interface not implemented by GNSS HAL", __func__);
609 } else {
610 mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
611 }
612 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100613 return mGnssMeasurement;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700614}
615
Martijn Coenen527924a2017-01-04 12:59:48 +0100616Return<sp<IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700617 if (mGnssIface == nullptr) {
618 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800619 return nullptr;
620 }
621
622 if (mGnssNavigationMessage == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700623 const GpsNavigationMessageInterface* gpsNavigationMessageIface =
624 static_cast<const GpsNavigationMessageInterface*>(
625 mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
626
627 if (gpsNavigationMessageIface == nullptr) {
628 ALOGE("%s GnssNavigationMessage interface not implemented by GNSS HAL",
629 __func__);
630 } else {
631 mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
632 }
633 }
634
Martijn Coenen527924a2017-01-04 12:59:48 +0100635 return mGnssNavigationMessage;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700636}
637
Martijn Coenen527924a2017-01-04 12:59:48 +0100638Return<sp<IGnssXtra>> Gnss::getExtensionXtra() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700639 if (mGnssIface == nullptr) {
640 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800641 return nullptr;
642 }
643
644 if (mGnssXtraIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700645 const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
646 mGnssIface->get_extension(GPS_XTRA_INTERFACE));
647
648 if (gpsXtraIface == nullptr) {
649 ALOGE("%s GnssXtra interface not implemented by HAL", __func__);
650 } else {
651 mGnssXtraIface = new GnssXtra(gpsXtraIface);
652 }
653 }
654
Martijn Coenen527924a2017-01-04 12:59:48 +0100655 return mGnssXtraIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700656}
657
Martijn Coenen527924a2017-01-04 12:59:48 +0100658Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700659 if (mGnssIface == nullptr) {
660 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800661 return nullptr;
662 }
663
664 if (mGnssDebug == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700665 const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
666 mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
667
668 if (gpsDebugIface == nullptr) {
669 ALOGE("%s: GnssDebug interface is not implemented by HAL", __func__);
670 } else {
671 mGnssDebug = new GnssDebug(gpsDebugIface);
672 }
673 }
674
Martijn Coenen527924a2017-01-04 12:59:48 +0100675 return mGnssDebug;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700676}
677
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800678Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() {
679 if (mGnssIface == nullptr) {
680 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800681 return nullptr;
682 }
683
684 if (mGnssBatching == nullptr) {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800685 hw_module_t* module;
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800686 const FlpLocationInterface* flpLocationIface = nullptr;
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800687 int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
688
689 if (err != 0) {
690 ALOGE("gnss flp hw_get_module failed: %d", err);
691 } else if (module == nullptr) {
692 ALOGE("Fused Location hw_get_module returned null module");
693 } else if (module->methods == nullptr) {
694 ALOGE("Fused Location hw_get_module returned null methods");
695 } else {
696 hw_device_t* device;
697 err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
698 if (err != 0) {
699 ALOGE("flpDevice open failed: %d", err);
700 } else {
701 flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
702 flpLocationIface = flpDevice->get_flp_interface(flpDevice);
703 }
704 }
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800705
706 if (flpLocationIface == nullptr) {
707 ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
708 } else {
709 mGnssBatching = new GnssBatching(flpLocationIface);
710 }
711 }
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800712 return mGnssBatching;
713}
714
Wyatt Riley917640b2017-03-16 16:25:55 -0700715void Gnss::handleHidlDeath() {
716 ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
717
718 // commands down to the HAL implementation
719 stop(); // stop ongoing GPS tracking
720 if (mGnssMeasurement != nullptr) {
721 mGnssMeasurement->close();
722 }
723 if (mGnssNavigationMessage != nullptr) {
724 mGnssNavigationMessage->close();
725 }
726 if (mGnssBatching != nullptr) {
727 mGnssBatching->stop();
728 mGnssBatching->cleanup();
729 }
730 cleanup();
731
732 /*
733 * This has died, so close it off in case (race condition) callbacks happen
734 * before HAL processes above messages.
735 */
736 sGnssCbIface = nullptr;
737}
738
Chris Phoenixab5c1e12017-01-23 15:14:08 -0800739IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700740 hw_module_t* module;
741 IGnss* iface = nullptr;
742 int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
743
744 if (err == 0) {
745 hw_device_t* device;
746 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
747 if (err == 0) {
748 iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
749 } else {
Chris Phoenixab5c1e12017-01-23 15:14:08 -0800750 ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700751 }
752 } else {
Chris Phoenixab5c1e12017-01-23 15:14:08 -0800753 ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700754 }
755 return iface;
756}
757
758} // namespace implementation
759} // namespace V1_0
760} // namespace gnss
761} // namespace hardware
762} // namespace android