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