1 /* Copyright (c) 2017, 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_NDDEBUG 0
31 #define LOG_TAG "LocSvc_GnssAPIClient"
32 
33 #include <log_util.h>
34 #include <loc_cfg.h>
35 
36 #include "LocationUtil.h"
37 #include "GnssAPIClient.h"
38 
39 namespace android {
40 namespace hardware {
41 namespace gnss {
42 namespace V1_0 {
43 namespace implementation {
44 
45 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
46 
GnssAPIClient(const sp<IGnssCallback> & gpsCb,const sp<IGnssNiCallback> & niCb)47 GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
48     const sp<IGnssNiCallback>& niCb) :
49     LocationAPIClientBase(),
50     mGnssCbIface(nullptr),
51     mGnssNiCbIface(nullptr),
52     mLocationCapabilitiesMask(0),
53     mLocationCapabilitiesCached(false)
54 {
55     LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
56 
57     // set default LocationOptions.
58     memset(&mLocationOptions, 0, sizeof(LocationOptions));
59     mLocationOptions.size = sizeof(LocationOptions);
60     mLocationOptions.minInterval = 1000;
61     mLocationOptions.minDistance = 0;
62     mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
63 
64     gnssUpdateCallbacks(gpsCb, niCb);
65 }
66 
~GnssAPIClient()67 GnssAPIClient::~GnssAPIClient()
68 {
69     LOC_LOGD("%s]: ()", __FUNCTION__);
70 }
71 
72 // for GpsInterface
gnssUpdateCallbacks(const sp<IGnssCallback> & gpsCb,const sp<IGnssNiCallback> & niCb)73 void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
74     const sp<IGnssNiCallback>& niCb)
75 {
76     LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
77     mMutex.lock();
78     mGnssCbIface = gpsCb;
79     mGnssNiCbIface = niCb;
80     mMutex.unlock();
81     LocationCallbacks locationCallbacks;
82     locationCallbacks.size = sizeof(LocationCallbacks);
83 
84     locationCallbacks.trackingCb = nullptr;
85     if (mGnssCbIface != nullptr) {
86         locationCallbacks.trackingCb = [this](Location location) {
87             onTrackingCb(location);
88         };
89     }
90 
91     locationCallbacks.batchingCb = nullptr;
92     locationCallbacks.geofenceBreachCb = nullptr;
93     locationCallbacks.geofenceStatusCb = nullptr;
94     locationCallbacks.gnssLocationInfoCb = nullptr;
95 
96     locationCallbacks.gnssNiCb = nullptr;
97     if (mGnssNiCbIface != nullptr) {
98         locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
99             onGnssNiCb(id, gnssNiNotification);
100         };
101     }
102 
103     locationCallbacks.gnssSvCb = nullptr;
104     if (mGnssCbIface != nullptr) {
105         locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
106             onGnssSvCb(gnssSvNotification);
107         };
108     }
109 
110     locationCallbacks.gnssNmeaCb = nullptr;
111     if (mGnssCbIface != nullptr) {
112         locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
113             onGnssNmeaCb(gnssNmeaNotification);
114         };
115     }
116 
117     locationCallbacks.gnssMeasurementsCb = nullptr;
118 
119     locAPISetCallbacks(locationCallbacks);
120 }
121 
gnssStart()122 bool GnssAPIClient::gnssStart()
123 {
124     LOC_LOGD("%s]: ()", __FUNCTION__);
125     bool retVal = true;
126     locAPIStartTracking(mLocationOptions);
127     return retVal;
128 }
129 
gnssStop()130 bool GnssAPIClient::gnssStop()
131 {
132     LOC_LOGD("%s]: ()", __FUNCTION__);
133     bool retVal = true;
134     locAPIStopTracking();
135     return retVal;
136 }
137 
gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)138 void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
139 {
140     LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
141     GnssAidingData data;
142     memset(&data, 0, sizeof (GnssAidingData));
143     data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
144         GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
145         GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
146         GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
147         GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
148 
149     if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
150         data.deleteAll = true;
151     else {
152         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
153             data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
154         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
155             data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
156         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
157             data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
158         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
159             data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
160         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
161             data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
162         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
163             data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
164         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
165             data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
166         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
167             data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
168         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
169             data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
170         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
171             data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
172         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
173             data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
174         if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
175             data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
176     }
177     locAPIGnssDeleteAidingData(data);
178 }
179 
gnssSetPositionMode(IGnss::GnssPositionMode mode,IGnss::GnssPositionRecurrence recurrence,uint32_t minIntervalMs,uint32_t preferredAccuracyMeters,uint32_t preferredTimeMs)180 bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
181         IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
182         uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs)
183 {
184     LOC_LOGD("%s]: (%d %d %d %d %d)", __FUNCTION__,
185             (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, preferredTimeMs);
186     bool retVal = true;
187     memset(&mLocationOptions, 0, sizeof(LocationOptions));
188     mLocationOptions.size = sizeof(LocationOptions);
189     mLocationOptions.minInterval = minIntervalMs;
190     mLocationOptions.minDistance = preferredAccuracyMeters;
191     if (mode == IGnss::GnssPositionMode::STANDALONE)
192         mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
193     else if (mode == IGnss::GnssPositionMode::MS_BASED)
194         mLocationOptions.mode = GNSS_SUPL_MODE_MSB;
195     else if (mode ==  IGnss::GnssPositionMode::MS_ASSISTED)
196         mLocationOptions.mode = GNSS_SUPL_MODE_MSA;
197     locAPIUpdateTrackingOptions(mLocationOptions);
198     return retVal;
199 }
200 
201 // for GpsNiInterface
gnssNiRespond(int32_t notifId,IGnssNiCallback::GnssUserResponseType userResponse)202 void GnssAPIClient::gnssNiRespond(int32_t notifId,
203         IGnssNiCallback::GnssUserResponseType userResponse)
204 {
205     LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
206     GnssNiResponse data = GNSS_NI_RESPONSE_IGNORE;
207     if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT)
208         data = GNSS_NI_RESPONSE_ACCEPT;
209     else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY)
210         data = GNSS_NI_RESPONSE_DENY;
211     else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP)
212         data = GNSS_NI_RESPONSE_NO_RESPONSE;
213     locAPIGnssNiResponse(notifId, data);
214 }
215 
216 // for GnssConfigurationInterface
gnssConfigurationUpdate(const GnssConfig & gnssConfig)217 void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
218 {
219     LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
220     locAPIGnssUpdateConfig(gnssConfig);
221 }
222 
requestCapabilities()223 void GnssAPIClient::requestCapabilities() {
224     // only send capablities if it's already cached, otherwise the first time LocationAPI
225     // is initialized, capabilities will be sent by LocationAPI
226     if (mLocationCapabilitiesCached) {
227         onCapabilitiesCb(mLocationCapabilitiesMask);
228     }
229 }
230 
231 // callbacks
onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)232 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
233 {
234     LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
235     mLocationCapabilitiesMask = capabilitiesMask;
236     mLocationCapabilitiesCached = true;
237 
238     mMutex.lock();
239     auto gnssCbIface(mGnssCbIface);
240     mMutex.unlock();
241 
242     if (gnssCbIface != nullptr) {
243         uint32_t data = 0;
244         if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
245                 (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
246                 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
247                 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
248             data |= IGnssCallback::Capabilities::SCHEDULING;
249         if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
250             data |= IGnssCallback::Capabilities::GEOFENCING;
251         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
252             data |= IGnssCallback::Capabilities::MEASUREMENTS;
253         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
254             data |= IGnssCallback::Capabilities::MSB;
255         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
256             data |= IGnssCallback::Capabilities::MSA;
257         auto r = gnssCbIface->gnssSetCapabilitesCb(data);
258         if (!r.isOk()) {
259             LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
260                 __func__, r.description().c_str());
261         }
262     }
263     if (gnssCbIface != nullptr) {
264         IGnssCallback::GnssSystemInfo gnssInfo;
265         gnssInfo.yearOfHw = 2015;
266         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
267             gnssInfo.yearOfHw = 2017;
268         }
269         LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
270         auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
271         if (!r.isOk()) {
272             LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
273                 __func__, r.description().c_str());
274         }
275     }
276 }
277 
onTrackingCb(Location location)278 void GnssAPIClient::onTrackingCb(Location location)
279 {
280     LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
281     mMutex.lock();
282     auto gnssCbIface(mGnssCbIface);
283     mMutex.unlock();
284 
285     if (gnssCbIface != nullptr) {
286         GnssLocation gnssLocation;
287         convertGnssLocation(location, gnssLocation);
288         auto r = gnssCbIface->gnssLocationCb(gnssLocation);
289         if (!r.isOk()) {
290             LOC_LOGE("%s] Error from gnssLocationCb description=%s",
291                 __func__, r.description().c_str());
292         }
293     }
294 }
295 
onGnssNiCb(uint32_t id,GnssNiNotification gnssNiNotification)296 void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
297 {
298     LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
299     mMutex.lock();
300     auto gnssNiCbIface(mGnssNiCbIface);
301     mMutex.unlock();
302 
303     if (gnssNiCbIface == nullptr) {
304         LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
305         return;
306     }
307 
308     IGnssNiCallback::GnssNiNotification notificationGnss = {};
309 
310     notificationGnss.notificationId = id;
311 
312     if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
313         notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
314     else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
315         notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
316     else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
317         notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
318     else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
319         notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
320 
321     if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
322         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
323     if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
324         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
325     if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
326         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
327 
328     notificationGnss.timeoutSec = gnssNiNotification.timeout;
329 
330     if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
331         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
332     else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
333         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
334     else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
335             gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
336         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
337 
338     notificationGnss.requestorId = gnssNiNotification.requestor;
339 
340     notificationGnss.notificationMessage = gnssNiNotification.message;
341 
342     if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
343         notificationGnss.requestorIdEncoding =
344             IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
345     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
346         notificationGnss.requestorIdEncoding =
347             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
348     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
349         notificationGnss.requestorIdEncoding =
350             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
351     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
352         notificationGnss.requestorIdEncoding =
353             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
354 
355     if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
356         notificationGnss.notificationIdEncoding =
357             IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
358     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
359         notificationGnss.notificationIdEncoding =
360             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
361     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
362         notificationGnss.notificationIdEncoding =
363             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
364     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
365         notificationGnss.notificationIdEncoding =
366             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
367 
368     gnssNiCbIface->niNotifyCb(notificationGnss);
369 }
370 
onGnssSvCb(GnssSvNotification gnssSvNotification)371 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
372 {
373     LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
374     mMutex.lock();
375     auto gnssCbIface(mGnssCbIface);
376     mMutex.unlock();
377 
378     if (gnssCbIface != nullptr) {
379         IGnssCallback::GnssSvStatus svStatus;
380         convertGnssSvStatus(gnssSvNotification, svStatus);
381         auto r = gnssCbIface->gnssSvStatusCb(svStatus);
382         if (!r.isOk()) {
383             LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
384                 __func__, r.description().c_str());
385         }
386     }
387 }
388 
onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)389 void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
390 {
391     mMutex.lock();
392     auto gnssCbIface(mGnssCbIface);
393     mMutex.unlock();
394 
395     if (gnssCbIface != nullptr) {
396         android::hardware::hidl_string nmeaString;
397         nmeaString.setToExternal(gnssNmeaNotification.nmea, gnssNmeaNotification.length);
398         auto r = gnssCbIface->gnssNmeaCb(
399             static_cast<GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
400         if (!r.isOk()) {
401             LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s", __func__,
402                 gnssNmeaNotification.nmea, gnssNmeaNotification.length, r.description().c_str());
403         }
404     }
405 }
406 
onStartTrackingCb(LocationError error)407 void GnssAPIClient::onStartTrackingCb(LocationError error)
408 {
409     LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
410     mMutex.lock();
411     auto gnssCbIface(mGnssCbIface);
412     mMutex.unlock();
413 
414     if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
415         auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
416         if (!r.isOk()) {
417             LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
418                 __func__, r.description().c_str());
419         }
420         r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
421         if (!r.isOk()) {
422             LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
423                 __func__, r.description().c_str());
424         }
425     }
426 }
427 
onStopTrackingCb(LocationError error)428 void GnssAPIClient::onStopTrackingCb(LocationError error)
429 {
430     LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
431     mMutex.lock();
432     auto gnssCbIface(mGnssCbIface);
433     mMutex.unlock();
434 
435     if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
436         auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
437         if (!r.isOk()) {
438             LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
439                 __func__, r.description().c_str());
440         }
441         r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
442         if (!r.isOk()) {
443             LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
444                 __func__, r.description().c_str());
445         }
446     }
447 }
448 
convertGnssSvStatus(GnssSvNotification & in,IGnssCallback::GnssSvStatus & out)449 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
450 {
451     memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
452     out.numSvs = in.count;
453     if (out.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
454         LOC_LOGW("%s]: Too many satellites %zd. Clamps to %d.",
455                 __FUNCTION__,  out.numSvs, GnssMax::SVS_COUNT);
456         out.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
457     }
458     for (size_t i = 0; i < out.numSvs; i++) {
459         IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
460         info.svid = in.gnssSvs[i].svId;
461         convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
462         info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
463         info.elevationDegrees = in.gnssSvs[i].elevation;
464         info.azimuthDegrees = in.gnssSvs[i].azimuth;
465         info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
466         info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
467         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
468             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
469         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
470             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
471         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
472             info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
473         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
474             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
475     }
476 }
477 
478 }  // namespace implementation
479 }  // namespace V1_0
480 }  // namespace gnss
481 }  // namespace hardware
482 }  // namespace android
483