Home | History | Annotate | Download | only in location_api
      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 
     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 
     69 GnssAPIClient::~GnssAPIClient()
     70 {
     71     LOC_LOGD("%s]: ()", __FUNCTION__);
     72     if (mControlClient) {
     73         delete mControlClient;
     74         mControlClient = nullptr;
     75     }
     76 }
     77 
     78 // for GpsInterface
     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 
    136 bool GnssAPIClient::gnssStart()
    137 {
    138     LOC_LOGD("%s]: ()", __FUNCTION__);
    139     bool retVal = true;
    140     locAPIStartTracking(mLocationOptions);
    141     return retVal;
    142 }
    143 
    144 bool GnssAPIClient::gnssStop()
    145 {
    146     LOC_LOGD("%s]: ()", __FUNCTION__);
    147     bool retVal = true;
    148     locAPIStopTracking();
    149     return retVal;
    150 }
    151 
    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
    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
    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 
    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 
    251 void GnssAPIClient::gnssDisable()
    252 {
    253     LOC_LOGD("%s]: ()", __FUNCTION__);
    254     if (mControlClient == nullptr) {
    255         return;
    256     }
    257     mControlClient->locAPIDisable();
    258 }
    259 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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