blob: 10024fbeafabf08c48e691efce44d9553b550091 [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
49Gnss::Gnss(gps_device_t* gnssDevice) {
50 /* Error out if an instance of the interface already exists. */
51 LOG_ALWAYS_FATAL_IF(sInterfaceExists);
52 sInterfaceExists = true;
53
54 if (gnssDevice == nullptr) {
55 ALOGE("%s: Invalid device_t handle", __func__);
56 return;
57 }
58
59 mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
60}
61
62Gnss::~Gnss() {
Hridya Valsarajue020ce22017-02-15 20:31:18 -080063 sInterfaceExists = false;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070064 sThreadFuncArgsList.clear();
65}
66
67void Gnss::locationCb(GpsLocation* location) {
68 if (sGnssCbIface == nullptr) {
69 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
70 return;
71 }
72
73 if (location == nullptr) {
74 ALOGE("%s: Invalid location from GNSS HAL", __func__);
75 return;
76 }
77
78 android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
Hridya Valsarajue020ce22017-02-15 20:31:18 -080079 auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
80 if (!ret.isOk()) {
81 ALOGE("%s: Unable to invoke callback", __func__);
82 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070083}
84
85void Gnss::statusCb(GpsStatus* gnssStatus) {
86 if (sGnssCbIface == nullptr) {
87 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
88 return;
89 }
90
91 if (gnssStatus == nullptr) {
92 ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
93 return;
94 }
95
96 IGnssCallback::GnssStatusValue status =
97 static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
98
Hridya Valsarajue020ce22017-02-15 20:31:18 -080099 auto ret = sGnssCbIface->gnssStatusCb(status);
100 if (!ret.isOk()) {
101 ALOGE("%s: Unable to invoke callback", __func__);
102 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700103}
104
105void Gnss::gnssSvStatusCb(GnssSvStatus* status) {
106 if (sGnssCbIface == nullptr) {
107 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
108 return;
109 }
110
111 if (status == nullptr) {
112 ALOGE("Invalid status from GNSS HAL %s", __func__);
113 return;
114 }
115
116 IGnssCallback::GnssSvStatus svStatus;
117 svStatus.numSvs = status->num_svs;
118
119 if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
120 ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
121 svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
122 }
123
124 for (size_t i = 0; i < svStatus.numSvs; i++) {
125 auto svInfo = status->gnss_sv_list[i];
126 IGnssCallback::GnssSvInfo gnssSvInfo = {
127 .svid = svInfo.svid,
128 .constellation = static_cast<android::hardware::gnss::V1_0::GnssConstellationType>(
129 svInfo.constellation),
130 .cN0Dbhz = svInfo.c_n0_dbhz,
131 .elevationDegrees = svInfo.elevation,
132 .azimuthDegrees = svInfo.azimuth,
gomoc3d92782017-01-11 14:04:21 -0800133 .svFlag = svInfo.flags,
134 // Older chipsets do not provide carrier frequency, hence HAS_CARRIER_FREQUENCY flag
135 // is not set and the carrierFrequencyHz field is set to zero
136 .carrierFrequencyHz = 0
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700137 };
138 svStatus.gnssSvList[i] = gnssSvInfo;
139 }
140
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800141 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
142 if (!ret.isOk()) {
143 ALOGE("%s: Unable to invoke callback", __func__);
144 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700145}
146
147/*
148 * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
149 * to GnssSvStatus for backward compatibility. It is only used by the default
150 * implementation and is not part of the GNSS interface.
151 */
152enum SvidValues : uint16_t {
153 GLONASS_SVID_OFFSET = 64,
154 GLONASS_SVID_COUNT = 24,
155 BEIDOU_SVID_OFFSET = 200,
156 BEIDOU_SVID_COUNT = 35,
157 SBAS_SVID_MIN = 33,
158 SBAS_SVID_MAX = 64,
159 SBAS_SVID_ADD = 87,
160 QZSS_SVID_MIN = 193,
161 QZSS_SVID_MAX = 200
162};
163
164/*
165 * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
166 * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
167 * being deprecated and is no longer part of the GNSS interface.
168 */
169void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
170 if (sGnssCbIface == nullptr) {
171 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
172 return;
173 }
174
175 if (svInfo == nullptr) {
176 ALOGE("Invalid status from GNSS HAL %s", __func__);
177 return;
178 }
179
180 IGnssCallback::GnssSvStatus svStatus;
181 svStatus.numSvs = svInfo->num_svs;
182 /*
183 * Clamp the list size since GnssSvStatus can support a maximum of
184 * GnssMax::SVS_COUNT entries.
185 */
186 if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
187 ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
188 svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
189 }
190
191 uint32_t ephemerisMask = svInfo->ephemeris_mask;
192 uint32_t almanacMask = svInfo->almanac_mask;
193 uint32_t usedInFixMask = svInfo->used_in_fix_mask;
194 /*
195 * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
196 */
197 for (size_t i = 0; i < svStatus.numSvs; i++) {
198 IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
199 info.svid = svInfo->sv_list[i].prn;
200 if (info.svid >= 1 && info.svid <= 32) {
201 info.constellation = GnssConstellationType::GPS;
202 } else if (info.svid > GLONASS_SVID_OFFSET &&
203 info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
204 info.constellation = GnssConstellationType::GLONASS;
205 info.svid -= GLONASS_SVID_OFFSET;
206 } else if (info.svid > BEIDOU_SVID_OFFSET &&
207 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
208 info.constellation = GnssConstellationType::BEIDOU;
209 info.svid -= BEIDOU_SVID_OFFSET;
210 } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
211 info.constellation = GnssConstellationType::SBAS;
212 info.svid += SBAS_SVID_ADD;
213 } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
214 info.constellation = GnssConstellationType::QZSS;
215 } else {
216 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
217 info.constellation = GnssConstellationType::UNKNOWN;
218 }
219
220 info.cN0Dbhz = svInfo->sv_list[i].snr;
221 info.elevationDegrees = svInfo->sv_list[i].elevation;
222 info.azimuthDegrees = svInfo->sv_list[i].azimuth;
Yifan Hong35e2aac2016-12-05 12:35:05 -0800223 // TODO: b/31702236
224 info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700225
226 /*
227 * Only GPS info is valid for these fields, as these masks are just 32
228 * bits, by GPS prn.
229 */
230 if (info.constellation == GnssConstellationType::GPS) {
231 int32_t svidMask = (1 << (info.svid - 1));
232 if ((ephemerisMask & svidMask) != 0) {
233 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
234 }
235 if ((almanacMask & svidMask) != 0) {
236 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
237 }
238 if ((usedInFixMask & svidMask) != 0) {
239 info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
240 }
241 }
242 }
243
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800244 auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
245 if (!ret.isOk()) {
246 ALOGE("%s: Unable to invoke callback", __func__);
247 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700248}
249
250void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
251 if (sGnssCbIface == nullptr) {
252 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
253 return;
254 }
255
256 android::hardware::hidl_string nmeaString;
257 nmeaString.setToExternal(nmea, length);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800258 auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
259 if (!ret.isOk()) {
260 ALOGE("%s: Unable to invoke callback", __func__);
261 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700262}
263
264void Gnss::setCapabilitiesCb(uint32_t capabilities) {
265 if (sGnssCbIface == nullptr) {
266 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
267 return;
268 }
269
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800270 auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
271 if (!ret.isOk()) {
272 ALOGE("%s: Unable to invoke callback", __func__);
273 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700274}
275
276void Gnss::acquireWakelockCb() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800277 acquireWakelockGnss();
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700278}
279
280void Gnss::releaseWakelockCb() {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800281 releaseWakelockGnss();
282}
283
284
285void Gnss::acquireWakelockGnss() {
286 sWakelockHeldGnss = true;
287 updateWakelock();
288}
289
290void Gnss::releaseWakelockGnss() {
291 sWakelockHeldGnss = false;
292 updateWakelock();
293}
294
295void Gnss::acquireWakelockFused() {
296 sWakelockHeldFused = true;
297 updateWakelock();
298}
299
300void Gnss::releaseWakelockFused() {
301 sWakelockHeldFused = false;
302 updateWakelock();
303}
304
305void Gnss::updateWakelock() {
306 // Track the state of the last request - in case the wake lock in the layer above is reference
307 // counted.
308 static bool sWakelockHeld = false;
309
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700310 if (sGnssCbIface == nullptr) {
311 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
312 return;
313 }
314
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800315 if (sWakelockHeldGnss || sWakelockHeldFused) {
316 if (!sWakelockHeld) {
317 ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
318 sWakelockHeldGnss, sWakelockHeldFused);
319 sWakelockHeld = true;
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800320 auto ret = sGnssCbIface->gnssAcquireWakelockCb();
321 if (!ret.isOk()) {
322 ALOGE("%s: Unable to invoke callback", __func__);
323 }
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800324 }
325 } else {
326 if (sWakelockHeld) {
327 ALOGI("%s: GNSS HAL Wakelock released", __func__);
328 } else {
329 // To avoid burning power, always release, even if logic got here with sWakelock false
330 // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
331 ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
332 }
333 sWakelockHeld = false;
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800334 auto ret = sGnssCbIface->gnssReleaseWakelockCb();
335 if (!ret.isOk()) {
336 ALOGE("%s: Unable to invoke callback", __func__);
337 }
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800338 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700339}
340
341void Gnss::requestUtcTimeCb() {
342 if (sGnssCbIface == nullptr) {
343 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
344 return;
345 }
346
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800347 auto ret = sGnssCbIface->gnssRequestTimeCb();
348 if (!ret.isOk()) {
349 ALOGE("%s: Unable to invoke callback", __func__);
350 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700351}
352
353pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
354 return createPthread(name, start, arg, &sThreadFuncArgsList);
355}
356
357void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
358 if (sGnssCbIface == nullptr) {
359 ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
360 return;
361 }
362
363 if (info == nullptr) {
364 ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
365 return;
366 }
367
368 IGnssCallback::GnssSystemInfo gnssInfo = {
369 .yearOfHw = info->year_of_hw
370 };
371
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800372 auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
373 if (!ret.isOk()) {
374 ALOGE("%s: Unable to invoke callback", __func__);
375 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700376}
377
378
379// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
380Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
381 if (mGnssIface == nullptr) {
382 ALOGE("%s: Gnss interface is unavailable", __func__);
383 return false;
384 }
385
386 sGnssCbIface = callback;
387
388 return (mGnssIface->init(&sGnssCb) == 0);
389}
390
391Return<bool> Gnss::start() {
392 if (mGnssIface == nullptr) {
393 ALOGE("%s: Gnss interface is unavailable", __func__);
394 return false;
395 }
396
397 return (mGnssIface->start() == 0);
398}
399
400Return<bool> Gnss::stop() {
401 if (mGnssIface == nullptr) {
402 ALOGE("%s: Gnss interface is unavailable", __func__);
403 return false;
404 }
405
406 return (mGnssIface->stop() == 0);
407}
408
409Return<void> Gnss::cleanup() {
410 if (mGnssIface == nullptr) {
411 ALOGE("%s: Gnss interface is unavailable", __func__);
412 } else {
413 mGnssIface->cleanup();
414 }
415 return Void();
416}
417
418Return<bool> Gnss::injectLocation(double latitudeDegrees,
419 double longitudeDegrees,
420 float accuracyMeters) {
421 if (mGnssIface == nullptr) {
422 ALOGE("%s: Gnss interface is unavailable", __func__);
423 return false;
424 }
425
426 return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
427}
428
429Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
430 int32_t uncertaintyMs) {
431 if (mGnssIface == nullptr) {
432 ALOGE("%s: Gnss interface is unavailable", __func__);
433 return false;
434 }
435
436 return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
437}
438
439Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags) {
440 if (mGnssIface == nullptr) {
441 ALOGE("%s: Gnss interface is unavailable", __func__);
442 } else {
443 mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
444 }
445 return Void();
446}
447
448Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
449 IGnss::GnssPositionRecurrence recurrence,
450 uint32_t minIntervalMs,
451 uint32_t preferredAccuracyMeters,
452 uint32_t preferredTimeMs) {
453 if (mGnssIface == nullptr) {
454 ALOGE("%s: Gnss interface is unavailable", __func__);
455 return false;
456 }
457
458 return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
459 static_cast<GpsPositionRecurrence>(recurrence),
460 minIntervalMs,
461 preferredAccuracyMeters,
462 preferredTimeMs) == 0);
463}
464
Martijn Coenen527924a2017-01-04 12:59:48 +0100465Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700466 if (mGnssIface == nullptr) {
467 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800468 return nullptr;
469 }
470
471 if (mGnssRil == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700472 const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
473 mGnssIface->get_extension(AGPS_RIL_INTERFACE));
474 if (agpsRilIface == nullptr) {
475 ALOGE("%s GnssRil interface not implemented by GNSS HAL", __func__);
476 } else {
477 mGnssRil = new AGnssRil(agpsRilIface);
478 }
479 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100480 return mGnssRil;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700481}
482
Martijn Coenen527924a2017-01-04 12:59:48 +0100483Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700484 if (mGnssIface == nullptr) {
485 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800486 return nullptr;
487 }
488
489 if (mGnssConfig == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700490 const GnssConfigurationInterface* gnssConfigIface =
491 static_cast<const GnssConfigurationInterface*>(
492 mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
493
494 if (gnssConfigIface == nullptr) {
495 ALOGE("%s GnssConfiguration interface not implemented by GNSS HAL", __func__);
496 } else {
497 mGnssConfig = new GnssConfiguration(gnssConfigIface);
498 }
499 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100500 return mGnssConfig;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700501}
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800502
Martijn Coenen527924a2017-01-04 12:59:48 +0100503Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700504 if (mGnssIface == nullptr) {
505 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800506 return nullptr;
507 }
508
509 if (mGnssGeofencingIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700510 const GpsGeofencingInterface* gpsGeofencingIface =
511 static_cast<const GpsGeofencingInterface*>(
512 mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
513
514 if (gpsGeofencingIface == nullptr) {
515 ALOGE("%s GnssGeofencing interface not implemented by GNSS HAL", __func__);
516 } else {
517 mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
518 }
519 }
520
Martijn Coenen527924a2017-01-04 12:59:48 +0100521 return mGnssGeofencingIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700522}
523
Martijn Coenen527924a2017-01-04 12:59:48 +0100524Return<sp<IAGnss>> Gnss::getExtensionAGnss() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700525 if (mGnssIface == nullptr) {
526 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800527 return nullptr;
528 }
529
530 if (mAGnssIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700531 const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
532 mGnssIface->get_extension(AGPS_INTERFACE));
533 if (agpsIface == nullptr) {
534 ALOGE("%s AGnss interface not implemented by GNSS HAL", __func__);
535 } else {
536 mAGnssIface = new AGnss(agpsIface);
537 }
538 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100539 return mAGnssIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700540}
541
Martijn Coenen527924a2017-01-04 12:59:48 +0100542Return<sp<IGnssNi>> Gnss::getExtensionGnssNi() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700543 if (mGnssIface == nullptr) {
544 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800545 return nullptr;
546 }
547
548 if (mGnssNi == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700549 const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
550 mGnssIface->get_extension(GPS_NI_INTERFACE));
551 if (gpsNiIface == nullptr) {
552 ALOGE("%s GnssNi interface not implemented by GNSS HAL", __func__);
553 } else {
554 mGnssNi = new GnssNi(gpsNiIface);
555 }
556 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100557 return mGnssNi;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700558}
559
Martijn Coenen527924a2017-01-04 12:59:48 +0100560Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
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 (mGnssMeasurement == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700567 const GpsMeasurementInterface* gpsMeasurementIface =
568 static_cast<const GpsMeasurementInterface*>(
569 mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
570
571 if (gpsMeasurementIface == nullptr) {
572 ALOGE("%s GnssMeasurement interface not implemented by GNSS HAL", __func__);
573 } else {
574 mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
575 }
576 }
Martijn Coenen527924a2017-01-04 12:59:48 +0100577 return mGnssMeasurement;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700578}
579
Martijn Coenen527924a2017-01-04 12:59:48 +0100580Return<sp<IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700581 if (mGnssIface == nullptr) {
582 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800583 return nullptr;
584 }
585
586 if (mGnssNavigationMessage == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700587 const GpsNavigationMessageInterface* gpsNavigationMessageIface =
588 static_cast<const GpsNavigationMessageInterface*>(
589 mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
590
591 if (gpsNavigationMessageIface == nullptr) {
592 ALOGE("%s GnssNavigationMessage interface not implemented by GNSS HAL",
593 __func__);
594 } else {
595 mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
596 }
597 }
598
Martijn Coenen527924a2017-01-04 12:59:48 +0100599 return mGnssNavigationMessage;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700600}
601
Martijn Coenen527924a2017-01-04 12:59:48 +0100602Return<sp<IGnssXtra>> Gnss::getExtensionXtra() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700603 if (mGnssIface == nullptr) {
604 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800605 return nullptr;
606 }
607
608 if (mGnssXtraIface == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700609 const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
610 mGnssIface->get_extension(GPS_XTRA_INTERFACE));
611
612 if (gpsXtraIface == nullptr) {
613 ALOGE("%s GnssXtra interface not implemented by HAL", __func__);
614 } else {
615 mGnssXtraIface = new GnssXtra(gpsXtraIface);
616 }
617 }
618
Martijn Coenen527924a2017-01-04 12:59:48 +0100619 return mGnssXtraIface;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700620}
621
Martijn Coenen527924a2017-01-04 12:59:48 +0100622Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug() {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700623 if (mGnssIface == nullptr) {
624 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800625 return nullptr;
626 }
627
628 if (mGnssDebug == nullptr) {
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700629 const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
630 mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
631
632 if (gpsDebugIface == nullptr) {
633 ALOGE("%s: GnssDebug interface is not implemented by HAL", __func__);
634 } else {
635 mGnssDebug = new GnssDebug(gpsDebugIface);
636 }
637 }
638
Martijn Coenen527924a2017-01-04 12:59:48 +0100639 return mGnssDebug;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700640}
641
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800642Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() {
643 if (mGnssIface == nullptr) {
644 ALOGE("%s: Gnss interface is unavailable", __func__);
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800645 return nullptr;
646 }
647
648 if (mGnssBatching == nullptr) {
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800649 hw_module_t* module;
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800650 const FlpLocationInterface* flpLocationIface = nullptr;
Wyatt Riley8791e7b2017-01-17 12:12:25 -0800651 int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
652
653 if (err != 0) {
654 ALOGE("gnss flp hw_get_module failed: %d", err);
655 } else if (module == nullptr) {
656 ALOGE("Fused Location hw_get_module returned null module");
657 } else if (module->methods == nullptr) {
658 ALOGE("Fused Location hw_get_module returned null methods");
659 } else {
660 hw_device_t* device;
661 err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
662 if (err != 0) {
663 ALOGE("flpDevice open failed: %d", err);
664 } else {
665 flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
666 flpLocationIface = flpDevice->get_flp_interface(flpDevice);
667 }
668 }
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800669
670 if (flpLocationIface == nullptr) {
671 ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
672 } else {
673 mGnssBatching = new GnssBatching(flpLocationIface);
674 }
675 }
Wyatt Rileyad03ab22016-12-14 14:54:29 -0800676 return mGnssBatching;
677}
678
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700679IGnss* HIDL_FETCH_IGnss(const char* hal) {
680 hw_module_t* module;
681 IGnss* iface = nullptr;
682 int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
683
684 if (err == 0) {
685 hw_device_t* device;
686 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
687 if (err == 0) {
688 iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
689 } else {
690 ALOGE("gnssDevice open %s failed: %d", hal, err);
691 }
692 } else {
693 ALOGE("gnss hw_get_module %s failed: %d", hal, err);
694 }
695 return iface;
696}
697
698} // namespace implementation
699} // namespace V1_0
700} // namespace gnss
701} // namespace hardware
702} // namespace android