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
40namespace android {
41namespace hardware {
42namespace gnss {
43namespace V1_0 {
44namespace implementation {
45
46static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
47
48GnssAPIClient::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
69GnssAPIClient::~GnssAPIClient()
70{
71    LOC_LOGD("%s]: ()", __FUNCTION__);
72    if (mControlClient) {
73        delete mControlClient;
74        mControlClient = nullptr;
75    }
76}
77
78// for GpsInterface
79void 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
136bool GnssAPIClient::gnssStart()
137{
138    LOC_LOGD("%s]: ()", __FUNCTION__);
139    bool retVal = true;
140    locAPIStartTracking(mLocationOptions);
141    return retVal;
142}
143
144bool GnssAPIClient::gnssStop()
145{
146    LOC_LOGD("%s]: ()", __FUNCTION__);
147    bool retVal = true;
148    locAPIStopTracking();
149    return retVal;
150}
151
152bool 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
178void 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
197void 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
242void 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
251void GnssAPIClient::gnssDisable()
252{
253    LOC_LOGD("%s]: ()", __FUNCTION__);
254    if (mControlClient == nullptr) {
255        return;
256    }
257    mControlClient->locAPIDisable();
258}
259
260void 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
269void 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
278void 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
327void 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
345void 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
420void 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
438void 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
456void 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
477void 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
498static 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