1 /* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #define LOG_NDEBUG 0
31 #define LOG_TAG "LocSvc_GnssAPIClient"
32 #define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
33
34 #include <inttypes.h>
35 #include <log_util.h>
36 #include <loc_cfg.h>
37
38 #include "LocationUtil.h"
39 #include "GnssAPIClient.h"
40 #include <LocContext.h>
41
42 namespace android {
43 namespace hardware {
44 namespace gnss {
45 namespace V1_0 {
46 namespace implementation {
47
48 using ::android::hardware::gnss::V1_0::IGnss;
49 using ::android::hardware::gnss::V1_0::IGnssCallback;
50 using ::android::hardware::gnss::V1_0::IGnssNiCallback;
51 using ::android::hardware::gnss::V1_0::GnssLocation;
52
53 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
54
GnssAPIClient(const sp<IGnssCallback> & gpsCb,const sp<IGnssNiCallback> & niCb)55 GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
56 const sp<IGnssNiCallback>& niCb) :
57 LocationAPIClientBase(),
58 mGnssCbIface(nullptr),
59 mGnssNiCbIface(nullptr),
60 mControlClient(new LocationAPIControlClient()),
61 mLocationCapabilitiesMask(0),
62 mLocationCapabilitiesCached(false)
63 {
64 LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
65
66 // set default LocationOptions.
67 memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
68 mTrackingOptions.size = sizeof(TrackingOptions);
69 mTrackingOptions.minInterval = 1000;
70 mTrackingOptions.minDistance = 0;
71 mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
72
73 gnssUpdateCallbacks(gpsCb, niCb);
74 }
75
~GnssAPIClient()76 GnssAPIClient::~GnssAPIClient()
77 {
78 LOC_LOGD("%s]: ()", __FUNCTION__);
79 if (mControlClient) {
80 delete mControlClient;
81 mControlClient = nullptr;
82 }
83 }
84
85 // for GpsInterface
gnssUpdateCallbacks(const sp<IGnssCallback> & gpsCb,const sp<IGnssNiCallback> & niCb)86 void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
87 const sp<IGnssNiCallback>& niCb)
88 {
89 LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
90
91 mMutex.lock();
92 mGnssCbIface = gpsCb;
93 mGnssNiCbIface = niCb;
94 mMutex.unlock();
95
96 LocationCallbacks locationCallbacks;
97 memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
98 locationCallbacks.size = sizeof(LocationCallbacks);
99
100 locationCallbacks.trackingCb = nullptr;
101 if (mGnssCbIface != nullptr) {
102 locationCallbacks.trackingCb = [this](Location location) {
103 onTrackingCb(location);
104 };
105 }
106
107 locationCallbacks.batchingCb = nullptr;
108 locationCallbacks.geofenceBreachCb = nullptr;
109 locationCallbacks.geofenceStatusCb = nullptr;
110 locationCallbacks.gnssLocationInfoCb = nullptr;
111
112 locationCallbacks.gnssNiCb = nullptr;
113 loc_core::ContextBase* context =
114 loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
115 if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
116 LOC_LOGD("Registering NI CB");
117 locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
118 onGnssNiCb(id, gnssNiNotification);
119 };
120 }
121
122 locationCallbacks.gnssSvCb = nullptr;
123 if (mGnssCbIface != nullptr) {
124 locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
125 onGnssSvCb(gnssSvNotification);
126 };
127 }
128
129 locationCallbacks.gnssNmeaCb = nullptr;
130 if (mGnssCbIface != nullptr) {
131 locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
132 onGnssNmeaCb(gnssNmeaNotification);
133 };
134 }
135
136 locationCallbacks.gnssMeasurementsCb = nullptr;
137
138 locAPISetCallbacks(locationCallbacks);
139 }
140
gnssStart()141 bool GnssAPIClient::gnssStart()
142 {
143 LOC_LOGD("%s]: ()", __FUNCTION__);
144 bool retVal = true;
145 locAPIStartTracking(mTrackingOptions);
146 return retVal;
147 }
148
gnssStop()149 bool GnssAPIClient::gnssStop()
150 {
151 LOC_LOGD("%s]: ()", __FUNCTION__);
152 bool retVal = true;
153 locAPIStopTracking();
154 return retVal;
155 }
156
gnssSetPositionMode(IGnss::GnssPositionMode mode,IGnss::GnssPositionRecurrence recurrence,uint32_t minIntervalMs,uint32_t preferredAccuracyMeters,uint32_t preferredTimeMs,GnssPowerMode powerMode,uint32_t timeBetweenMeasurement)157 bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
158 IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
159 uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
160 GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
161 {
162 LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
163 (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
164 preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
165 bool retVal = true;
166 memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
167 mTrackingOptions.size = sizeof(TrackingOptions);
168 mTrackingOptions.minInterval = minIntervalMs;
169 if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
170 IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
171 // We set a very large interval to simulate SINGLE mode. Once we report a fix,
172 // the caller should take the responsibility to stop the session.
173 // For MSA, we always treat it as SINGLE mode.
174 mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
175 }
176 if (mode == IGnss::GnssPositionMode::STANDALONE)
177 mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
178 else if (mode == IGnss::GnssPositionMode::MS_BASED)
179 mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
180 else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
181 mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
182 else {
183 LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
184 retVal = false;
185 }
186 if (GNSS_POWER_MODE_INVALID != powerMode) {
187 mTrackingOptions.powerMode = powerMode;
188 mTrackingOptions.tbm = timeBetweenMeasurement;
189 }
190 locAPIUpdateTrackingOptions(mTrackingOptions);
191 return retVal;
192 }
193
194 // for GpsNiInterface
gnssNiRespond(int32_t notifId,IGnssNiCallback::GnssUserResponseType userResponse)195 void GnssAPIClient::gnssNiRespond(int32_t notifId,
196 IGnssNiCallback::GnssUserResponseType userResponse)
197 {
198 LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
199 GnssNiResponse data;
200 switch (userResponse) {
201 case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
202 data = GNSS_NI_RESPONSE_ACCEPT;
203 break;
204 case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
205 data = GNSS_NI_RESPONSE_DENY;
206 break;
207 case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
208 data = GNSS_NI_RESPONSE_NO_RESPONSE;
209 break;
210 default:
211 data = GNSS_NI_RESPONSE_IGNORE;
212 break;
213 }
214
215 locAPIGnssNiResponse(notifId, data);
216 }
217
218 // these apis using LocationAPIControlClient
gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)219 void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
220 {
221 LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
222 if (mControlClient == nullptr) {
223 return;
224 }
225 GnssAidingData data;
226 memset(&data, 0, sizeof (GnssAidingData));
227 data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
228 GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
229 GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
230 GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
231 GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
232 data.posEngineMask = STANDARD_POSITIONING_ENGINE;
233
234 if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
235 data.deleteAll = true;
236 else {
237 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
238 data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
239 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
240 data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
241 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
242 data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
243 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
244 data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
245 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
246 data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
247 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
248 data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
249 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
250 data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
251 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
252 data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
253 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
254 data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
255 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
256 data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
257 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
258 data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
259 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
260 data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
261 }
262 mControlClient->locAPIGnssDeleteAidingData(data);
263 }
264
gnssEnable(LocationTechnologyType techType)265 void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
266 {
267 LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
268 if (mControlClient == nullptr) {
269 return;
270 }
271 mControlClient->locAPIEnable(techType);
272 }
273
gnssDisable()274 void GnssAPIClient::gnssDisable()
275 {
276 LOC_LOGD("%s]: ()", __FUNCTION__);
277 if (mControlClient == nullptr) {
278 return;
279 }
280 mControlClient->locAPIDisable();
281 }
282
gnssConfigurationUpdate(const GnssConfig & gnssConfig)283 void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
284 {
285 LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
286 if (mControlClient == nullptr) {
287 return;
288 }
289 mControlClient->locAPIGnssUpdateConfig(gnssConfig);
290 }
291
requestCapabilities()292 void GnssAPIClient::requestCapabilities() {
293 // only send capablities if it's already cached, otherwise the first time LocationAPI
294 // is initialized, capabilities will be sent by LocationAPI
295 if (mLocationCapabilitiesCached) {
296 onCapabilitiesCb(mLocationCapabilitiesMask);
297 }
298 }
299
300 // callbacks
onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)301 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
302 {
303 LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
304 mLocationCapabilitiesMask = capabilitiesMask;
305 mLocationCapabilitiesCached = true;
306
307 mMutex.lock();
308 auto gnssCbIface(mGnssCbIface);
309 mMutex.unlock();
310
311 if (gnssCbIface != nullptr) {
312 uint32_t data = 0;
313 if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
314 (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
315 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
316 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
317 data |= IGnssCallback::Capabilities::SCHEDULING;
318 if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
319 data |= IGnssCallback::Capabilities::GEOFENCING;
320 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
321 data |= IGnssCallback::Capabilities::MEASUREMENTS;
322 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
323 data |= IGnssCallback::Capabilities::MSB;
324 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
325 data |= IGnssCallback::Capabilities::MSA;
326 auto r = gnssCbIface->gnssSetCapabilitesCb(data);
327 if (!r.isOk()) {
328 LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
329 __func__, r.description().c_str());
330 }
331 }
332 if (gnssCbIface != nullptr) {
333 IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
334
335 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
336 gnssInfo.yearOfHw++; // 2016
337 if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
338 gnssInfo.yearOfHw++; // 2017
339 if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
340 capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
341 gnssInfo.yearOfHw++; // 2018
342 }
343 }
344 }
345 LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
346 auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
347 if (!r.isOk()) {
348 LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
349 __func__, r.description().c_str());
350 }
351 }
352 }
353
onTrackingCb(Location location)354 void GnssAPIClient::onTrackingCb(Location location)
355 {
356 LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
357 mMutex.lock();
358 auto gnssCbIface(mGnssCbIface);
359 mMutex.unlock();
360
361 if (gnssCbIface != nullptr) {
362 GnssLocation gnssLocation;
363 convertGnssLocation(location, gnssLocation);
364 auto r = gnssCbIface->gnssLocationCb(gnssLocation);
365 if (!r.isOk()) {
366 LOC_LOGE("%s] Error from gnssLocationCb description=%s",
367 __func__, r.description().c_str());
368 }
369 }
370 }
371
onGnssNiCb(uint32_t id,GnssNiNotification gnssNiNotification)372 void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
373 {
374 LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
375 mMutex.lock();
376 auto gnssNiCbIface(mGnssNiCbIface);
377 mMutex.unlock();
378
379 if (gnssNiCbIface == nullptr) {
380 LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
381 return;
382 }
383
384 IGnssNiCallback::GnssNiNotification notificationGnss = {};
385
386 notificationGnss.notificationId = id;
387
388 if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
389 notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
390 else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
391 notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
392 else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
393 notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
394 else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
395 notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
396
397 if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
398 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
399 if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
400 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
401 if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
402 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
403
404 notificationGnss.timeoutSec = gnssNiNotification.timeout;
405
406 if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
407 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
408 else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
409 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
410 else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
411 gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
412 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
413
414 notificationGnss.requestorId = gnssNiNotification.requestor;
415
416 notificationGnss.notificationMessage = gnssNiNotification.message;
417
418 if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
419 notificationGnss.requestorIdEncoding =
420 IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
421 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
422 notificationGnss.requestorIdEncoding =
423 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
424 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
425 notificationGnss.requestorIdEncoding =
426 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
427 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
428 notificationGnss.requestorIdEncoding =
429 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
430
431 if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
432 notificationGnss.notificationIdEncoding =
433 IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
434 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
435 notificationGnss.notificationIdEncoding =
436 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
437 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
438 notificationGnss.notificationIdEncoding =
439 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
440 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
441 notificationGnss.notificationIdEncoding =
442 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
443
444 gnssNiCbIface->niNotifyCb(notificationGnss);
445 }
446
onGnssSvCb(GnssSvNotification gnssSvNotification)447 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
448 {
449 LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
450 mMutex.lock();
451 auto gnssCbIface(mGnssCbIface);
452 mMutex.unlock();
453
454 if (gnssCbIface != nullptr) {
455 IGnssCallback::GnssSvStatus svStatus;
456 convertGnssSvStatus(gnssSvNotification, svStatus);
457 auto r = gnssCbIface->gnssSvStatusCb(svStatus);
458 if (!r.isOk()) {
459 LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
460 __func__, r.description().c_str());
461 }
462 }
463 }
464
onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)465 void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
466 {
467 mMutex.lock();
468 auto gnssCbIface(mGnssCbIface);
469 mMutex.unlock();
470
471 if (gnssCbIface != nullptr) {
472 const std::string s(gnssNmeaNotification.nmea);
473 std::stringstream ss(s);
474 std::string each;
475 while(std::getline(ss, each, '\n')) {
476 each += '\n';
477 android::hardware::hidl_string nmeaString;
478 nmeaString.setToExternal(each.c_str(), each.length());
479 auto r = gnssCbIface->gnssNmeaCb(
480 static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
481 if (!r.isOk()) {
482 LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
483 gnssNmeaNotification.nmea, gnssNmeaNotification.length,
484 r.description().c_str());
485 }
486 }
487 }
488 }
489
onStartTrackingCb(LocationError error)490 void GnssAPIClient::onStartTrackingCb(LocationError error)
491 {
492 LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
493 mMutex.lock();
494 auto gnssCbIface(mGnssCbIface);
495 mMutex.unlock();
496
497 if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
498 auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
499 if (!r.isOk()) {
500 LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
501 __func__, r.description().c_str());
502 }
503 r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
504 if (!r.isOk()) {
505 LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
506 __func__, r.description().c_str());
507 }
508 }
509 }
510
onStopTrackingCb(LocationError error)511 void GnssAPIClient::onStopTrackingCb(LocationError error)
512 {
513 LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
514 mMutex.lock();
515 auto gnssCbIface(mGnssCbIface);
516 mMutex.unlock();
517
518 if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
519 auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
520 if (!r.isOk()) {
521 LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
522 __func__, r.description().c_str());
523 }
524 r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
525 if (!r.isOk()) {
526 LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
527 __func__, r.description().c_str());
528 }
529 }
530 }
531
convertGnssSvStatus(GnssSvNotification & in,IGnssCallback::GnssSvStatus & out)532 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
533 {
534 memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
535 out.numSvs = in.count;
536 if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
537 LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
538 __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT);
539 out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
540 }
541 for (size_t i = 0; i < out.numSvs; i++) {
542 IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
543 convertGnssSvid(in.gnssSvs[i], info.svid);
544 convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
545 info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
546 info.elevationDegrees = in.gnssSvs[i].elevation;
547 info.azimuthDegrees = in.gnssSvs[i].azimuth;
548 info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
549 info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
550 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
551 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
552 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
553 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
554 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
555 info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
556 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
557 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
558 }
559 }
560
561 } // namespace implementation
562 } // namespace V1_0
563 } // namespace gnss
564 } // namespace hardware
565 } // namespace android
566