blob: 16f2bf3cd0c4ec1a2a17310f79c26a1cfa537706 [file] [log] [blame]
Yu-Han Yangc06b5362019-10-25 14:14:35 -07001/*
2 * Copyright (C) 2019 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 "Gnss"
18
19#include "Gnss.h"
Yipeng Cao48618f62020-03-19 18:11:16 -070020#include <log/log.h>
21#include <sys/epoll.h>
22#include <string>
Sasha Kuznetsov768de572020-02-11 06:00:10 +000023#include "GnssAntennaInfo.h"
Sasha Kuznetsov216311f2020-01-02 17:23:42 -080024#include "GnssDebug.h"
Yu-Han Yangc06b5362019-10-25 14:14:35 -070025#include "GnssMeasurement.h"
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -080026#include "GnssMeasurementCorrections.h"
Yu-Han Yangc06b5362019-10-25 14:14:35 -070027#include "Utils.h"
28
Yu-Han Yangc06b5362019-10-25 14:14:35 -070029using ::android::hardware::gnss::common::Utils;
Sasha Kuznetsov31eea852020-01-03 13:06:38 -080030using ::android::hardware::gnss::measurement_corrections::V1_1::implementation::
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -080031 GnssMeasurementCorrections;
Yu-Han Yangc06b5362019-10-25 14:14:35 -070032
33namespace android {
34namespace hardware {
35namespace gnss {
36namespace V2_1 {
37namespace implementation {
38
39sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -080040sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
Sasha Kuznetsov216311f2020-01-02 17:23:42 -080041sp<V1_1::IGnssCallback> Gnss::sGnssCallback_1_1 = nullptr;
42sp<V1_0::IGnssCallback> Gnss::sGnssCallback_1_0 = nullptr;
Yu-Han Yangc06b5362019-10-25 14:14:35 -070043
Yipeng Cao48618f62020-03-19 18:11:16 -070044Gnss::Gnss()
45 : mMinIntervalMs(1000),
46 mGnssConfiguration{new GnssConfiguration()},
47 mHardwareModeOn(false),
48 mGnssFd(-1) {}
Yu-Han Yangc06b5362019-10-25 14:14:35 -070049
50Gnss::~Gnss() {
51 stop();
52}
53
Yipeng Cao48618f62020-03-19 18:11:16 -070054std::unique_ptr<V2_0::GnssLocation> Gnss::getLocationFromHW() {
55 char inputBuffer[INPUT_BUFFER_SIZE];
56 mHardwareModeOn = false;
57 if (mGnssFd == -1) {
58 mGnssFd = open(GNSS_PATH, O_RDWR | O_NONBLOCK);
59 }
60 if (mGnssFd == -1) {
61 return nullptr;
62 }
63 // Send control message to device
64 int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
65 if (bytes_write <= 0) {
66 return nullptr;
67 }
68
69 struct epoll_event ev, events[1];
70 ev.data.fd = mGnssFd;
71 ev.events = EPOLLIN;
72 int epoll_fd = epoll_create1(0);
73 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
74 int bytes_read = -1;
75 std::string inputStr = "";
76 int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
77 // Indicates it is a hardwareMode, don't need to wait outside.
78 mHardwareModeOn = true;
79 if (epoll_ret == -1) {
80 return nullptr;
81 }
82 while (true) {
83 bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
84 if (bytes_read <= 0) {
85 break;
86 }
87 inputStr += std::string(inputBuffer, bytes_read);
88 }
89 return NmeaFixInfo::getLocationFromInputStr(inputStr);
90}
91
Yu-Han Yangc06b5362019-10-25 14:14:35 -070092Return<bool> Gnss::start() {
Yu-Han Yangc06b5362019-10-25 14:14:35 -070093 if (mIsActive) {
94 ALOGW("Gnss has started. Restarting...");
95 stop();
96 }
97
98 mIsActive = true;
99 mThread = std::thread([this]() {
100 while (mIsActive == true) {
Sasha Kuznetsov845f6d52019-12-04 12:17:50 -0800101 auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700102 this->reportSvStatus(svStatus);
103
Yipeng Cao48618f62020-03-19 18:11:16 -0700104 auto currentLocation = getLocationFromHW();
105 if (currentLocation != nullptr) {
106 this->reportLocation(*currentLocation);
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800107 } else {
Yipeng Cao48618f62020-03-19 18:11:16 -0700108 if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
109 const auto location = Utils::getMockLocationV2_0();
110 this->reportLocation(location);
111 } else {
112 const auto location = Utils::getMockLocationV1_0();
113 this->reportLocation(location);
114 }
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700115
Yipeng Cao48618f62020-03-19 18:11:16 -0700116 // Only need do the sleep in the static location mode, which mocks the "wait
117 // for" hardware behavior.
118 if (!mHardwareModeOn) {
119 std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
120 }
121 }
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700122 }
123 });
124 return true;
125}
126
Sasha Kuznetsov845f6d52019-12-04 12:17:50 -0800127hidl_vec<GnssSvInfo> Gnss::filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList) {
128 for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
129 if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) {
130 gnssSvInfoList[i].v2_0.v1_0.svFlag &=
131 ~static_cast<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
132 }
133 }
134 return gnssSvInfoList;
135}
136
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700137Return<bool> Gnss::stop() {
138 ALOGD("stop");
139 mIsActive = false;
140 if (mThread.joinable()) {
141 mThread.join();
142 }
Yipeng Cao48618f62020-03-19 18:11:16 -0700143 if (mGnssFd != -1) {
144 close(mGnssFd);
145 mGnssFd = -1;
146 }
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700147 return true;
148}
149
150// Methods from V1_0::IGnss follow.
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800151Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
152 if (callback == nullptr) {
153 ALOGE("%s: Null callback ignored", __func__);
154 return false;
155 }
156
157 sGnssCallback_1_0 = callback;
158
159 uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS |
160 V1_0::IGnssCallback::Capabilities::SCHEDULING;
161 auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities);
162 if (!ret.isOk()) {
163 ALOGE("%s: Unable to invoke callback", __func__);
164 }
165
166 IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
167
168 ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo);
169 if (!ret.isOk()) {
170 ALOGE("%s: Unable to invoke callback", __func__);
171 }
172
173 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700174}
175
176Return<void> Gnss::cleanup() {
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800177 sGnssCallback_2_1 = nullptr;
178 sGnssCallback_2_0 = nullptr;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700179 return Void();
180}
181
182Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800183 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700184}
185
186Return<bool> Gnss::injectLocation(double, double, float) {
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800187 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700188}
189
190Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) {
191 // TODO implement
192 return Void();
193}
194
195Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800196 V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
197 uint32_t, uint32_t) {
198 mMinIntervalMs = minIntervalMs;
199 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700200}
201
202Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
203 // TODO implement
204 return ::android::sp<V1_0::IAGnssRil>{};
205}
206
207Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
208 // TODO implement
209 return ::android::sp<V1_0::IGnssGeofencing>{};
210}
211
212Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
213 // TODO implement
214 return ::android::sp<V1_0::IAGnss>{};
215}
216
217Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
218 // TODO implement
219 return ::android::sp<V1_0::IGnssNi>{};
220}
221
222Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800223 ALOGD("Gnss::getExtensionGnssMeasurement");
224 return new GnssMeasurement();
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700225}
226
227Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
228 // TODO implement
229 return ::android::sp<V1_0::IGnssNavigationMessage>{};
230}
231
232Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
233 // TODO implement
234 return ::android::sp<V1_0::IGnssXtra>{};
235}
236
237Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
238 // TODO implement
239 return ::android::sp<V1_0::IGnssConfiguration>{};
240}
241
242Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800243 return new V1_1::implementation::GnssDebug();
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700244}
245
246Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
247 // TODO implement
248 return ::android::sp<V1_0::IGnssBatching>{};
249}
250
251// Methods from V1_1::IGnss follow.
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800252Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
253 if (callback == nullptr) {
254 ALOGE("%s: Null callback ignored", __func__);
255 return false;
256 }
257
258 sGnssCallback_1_1 = callback;
259
260 uint32_t capabilities = 0x0;
261 auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities);
262 if (!ret.isOk()) {
263 ALOGE("%s: Unable to invoke callback", __func__);
264 }
265
266 IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
267
268 ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo);
269 if (!ret.isOk()) {
270 ALOGE("%s: Unable to invoke callback", __func__);
271 }
272
273 auto gnssName = "Google Mock GNSS Implementation v2.1";
274 ret = sGnssCallback_1_1->gnssNameCb(gnssName);
275 if (!ret.isOk()) {
276 ALOGE("%s: Unable to invoke callback", __func__);
277 }
278
279 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700280}
281
282Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800283 V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
284 uint32_t, uint32_t, bool) {
285 mMinIntervalMs = minIntervalMs;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700286 return true;
287}
288
289Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
290 // TODO implement
291 return ::android::sp<V1_1::IGnssConfiguration>{};
292}
293
294Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
295 // TODO implement
296 return ::android::sp<V1_1::IGnssMeasurement>{};
297}
298
299Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800300 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700301}
302
303// Methods from V2_0::IGnss follow.
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -0800304Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
305 ALOGD("Gnss::setCallback_2_0");
306 if (callback == nullptr) {
307 ALOGE("%s: Null callback ignored", __func__);
308 return false;
309 }
310
311 sGnssCallback_2_0 = callback;
312
313 using Capabilities = V2_0::IGnssCallback::Capabilities;
314 const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
315 Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
316 auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
317 if (!ret.isOk()) {
318 ALOGE("%s: Unable to invoke callback", __func__);
319 }
320
321 V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019};
322
323 ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo);
324 if (!ret.isOk()) {
325 ALOGE("%s: Unable to invoke callback", __func__);
326 }
327
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800328 auto gnssName = "Google Mock GNSS Implementation v2.1";
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -0800329 ret = sGnssCallback_2_0->gnssNameCb(gnssName);
330 if (!ret.isOk()) {
331 ALOGE("%s: Unable to invoke callback", __func__);
332 }
333
334 return true;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700335}
336
337Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -0800338 ALOGD("Gnss::getExtensionGnssConfiguration_2_0");
339 return mGnssConfiguration;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700340}
341
342Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
343 // TODO implement
344 return ::android::sp<V2_0::IGnssDebug>{};
345}
346
347Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
348 // TODO implement
349 return ::android::sp<V2_0::IAGnss>{};
350}
351
352Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
353 // TODO implement
354 return ::android::sp<V2_0::IAGnssRil>{};
355}
356
357Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -0800358 ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
359 return new GnssMeasurement();
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700360}
361
362Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
363Gnss::getExtensionMeasurementCorrections() {
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800364 ALOGD("Gnss::getExtensionMeasurementCorrections()");
365 return new GnssMeasurementCorrections();
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700366}
367
368Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
369 // TODO implement
370 return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
371}
372
373Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
374 // TODO implement
375 return ::android::sp<V2_0::IGnssBatching>{};
376}
377
378Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) {
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800379 // TODO(b/124012850): Implement function.
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700380 return bool{};
381}
382
383// Methods from V2_1::IGnss follow.
384Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
385 ALOGD("Gnss::setCallback_2_1");
386 if (callback == nullptr) {
387 ALOGE("%s: Null callback ignored", __func__);
388 return false;
389 }
390
391 sGnssCallback_2_1 = callback;
392
Sasha Kuznetsov768de572020-02-11 06:00:10 +0000393 using Capabilities = V2_1::IGnssCallback::Capabilities;
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700394 const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
Sasha Kuznetsov768de572020-02-11 06:00:10 +0000395 Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST |
396 Capabilities::ANTENNA_INFO;
Yu-Han Yang99b6d962020-02-13 14:19:09 -0800397 auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities);
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700398 if (!ret.isOk()) {
399 ALOGE("%s: Unable to invoke callback", __func__);
400 }
401
402 V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020};
403
404 ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo);
405 if (!ret.isOk()) {
406 ALOGE("%s: Unable to invoke callback", __func__);
407 }
408
409 auto gnssName = "Android Mock GNSS Implementation v2.1";
410 ret = sGnssCallback_2_1->gnssNameCb(gnssName);
411 if (!ret.isOk()) {
412 ALOGE("%s: Unable to invoke callback", __func__);
413 }
414
415 return true;
416}
417
418Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
419 ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
420 return new GnssMeasurement();
421}
422
Sasha Kuznetsov845f6d52019-12-04 12:17:50 -0800423Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
Sasha Kuznetsovc1c257b2019-12-13 13:08:16 -0800424 ALOGD("Gnss::getExtensionGnssConfiguration_2_1");
Sasha Kuznetsov845f6d52019-12-04 12:17:50 -0800425 return mGnssConfiguration;
426}
427
Sasha Kuznetsov31eea852020-01-03 13:06:38 -0800428Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
429Gnss::getExtensionMeasurementCorrections_1_1() {
430 ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()");
431 return new GnssMeasurementCorrections();
432}
433
Sasha Kuznetsov768de572020-02-11 06:00:10 +0000434Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
435 ALOGD("Gnss::getExtensionGnssAntennaInfo");
436 return new GnssAntennaInfo();
437}
438
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700439void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
440 std::unique_lock<std::mutex> lock(mMutex);
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800441 // TODO(skz): update this to call 2_0 callback if non-null
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700442 if (sGnssCallback_2_1 == nullptr) {
443 ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
444 return;
445 }
446 auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList);
447 if (!ret.isOk()) {
448 ALOGE("%s: Unable to invoke callback", __func__);
449 }
450}
451
Sasha Kuznetsov216311f2020-01-02 17:23:42 -0800452void Gnss::reportLocation(const V1_0::GnssLocation& location) const {
453 std::unique_lock<std::mutex> lock(mMutex);
454 if (sGnssCallback_1_1 != nullptr) {
455 auto ret = sGnssCallback_1_1->gnssLocationCb(location);
456 if (!ret.isOk()) {
457 ALOGE("%s: Unable to invoke callback v1.1", __func__);
458 }
459 return;
460 }
461 if (sGnssCallback_1_0 == nullptr) {
462 ALOGE("%s: No non-null callback", __func__);
463 return;
464 }
465 auto ret = sGnssCallback_1_0->gnssLocationCb(location);
466 if (!ret.isOk()) {
467 ALOGE("%s: Unable to invoke callback v1.0", __func__);
468 }
469}
470
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700471void Gnss::reportLocation(const V2_0::GnssLocation& location) const {
472 std::unique_lock<std::mutex> lock(mMutex);
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800473 if (sGnssCallback_2_1 != nullptr) {
474 auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location);
475 if (!ret.isOk()) {
476 ALOGE("%s: Unable to invoke callback v2.1", __func__);
477 }
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700478 return;
479 }
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800480 if (sGnssCallback_2_0 == nullptr) {
481 ALOGE("%s: No non-null callback", __func__);
482 return;
483 }
484 auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location);
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700485 if (!ret.isOk()) {
Sasha Kuznetsov7fd5cc32019-12-09 17:11:08 -0800486 ALOGE("%s: Unable to invoke callback v2.0", __func__);
Yu-Han Yangc06b5362019-10-25 14:14:35 -0700487 }
488}
489
490} // namespace implementation
491} // namespace V2_1
492} // namespace gnss
493} // namespace hardware
494} // namespace android