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_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 
     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 
     67 GnssAPIClient::~GnssAPIClient()
     68 {
     69     LOC_LOGD("%s]: ()", __FUNCTION__);
     70 }
     71 
     72 // for GpsInterface
     73 void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
     74     const sp<IGnssNiCallback>& niCb)
     75 {
     76     LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
     77 
     78     mGnssCbIface = gpsCb;
     79     mGnssNiCbIface = niCb;
     80 
     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 
    122 bool GnssAPIClient::gnssStart()
    123 {
    124     LOC_LOGD("%s]: ()", __FUNCTION__);
    125     bool retVal = true;
    126     locAPIStartTracking(mLocationOptions);
    127     return retVal;
    128 }
    129 
    130 bool GnssAPIClient::gnssStop()
    131 {
    132     LOC_LOGD("%s]: ()", __FUNCTION__);
    133     bool retVal = true;
    134     locAPIStopTracking();
    135     return retVal;
    136 }
    137 
    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 
    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
    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
    217 void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
    218 {
    219     LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
    220     locAPIGnssUpdateConfig(gnssConfig);
    221 }
    222 
    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
    232 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
    233 {
    234     LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
    235     mLocationCapabilitiesMask = capabilitiesMask;
    236     mLocationCapabilitiesCached = true;
    237     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    238 
    239     if (gnssCbIface != nullptr) {
    240         uint32_t data = 0;
    241         if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
    242                 (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
    243                 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
    244                 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
    245             data |= IGnssCallback::Capabilities::SCHEDULING;
    246         if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
    247             data |= IGnssCallback::Capabilities::GEOFENCING;
    248         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
    249             data |= IGnssCallback::Capabilities::MEASUREMENTS;
    250         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
    251             data |= IGnssCallback::Capabilities::MSB;
    252         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
    253             data |= IGnssCallback::Capabilities::MSA;
    254         auto r = gnssCbIface->gnssSetCapabilitesCb(data);
    255         if (!r.isOk()) {
    256             LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
    257                 __func__, r.description().c_str());
    258         }
    259     }
    260     if (gnssCbIface != nullptr) {
    261         IGnssCallback::GnssSystemInfo gnssInfo;
    262         gnssInfo.yearOfHw = 2015;
    263         if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
    264             gnssInfo.yearOfHw = 2017;
    265         }
    266         LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
    267         auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
    268         if (!r.isOk()) {
    269             LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
    270                 __func__, r.description().c_str());
    271         }
    272     }
    273 }
    274 
    275 void GnssAPIClient::onTrackingCb(Location location)
    276 {
    277     LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
    278     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    279 
    280     if (gnssCbIface != nullptr) {
    281         GnssLocation gnssLocation;
    282         convertGnssLocation(location, gnssLocation);
    283         auto r = gnssCbIface->gnssLocationCb(gnssLocation);
    284         if (!r.isOk()) {
    285             LOC_LOGE("%s] Error from gnssLocationCb description=%s",
    286                 __func__, r.description().c_str());
    287         }
    288     }
    289 }
    290 
    291 void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
    292 {
    293     LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
    294     sp<IGnssNiCallback> gnssNiCbIface = mGnssNiCbIface;
    295 
    296     if (gnssNiCbIface == nullptr) {
    297         LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
    298         return;
    299     }
    300 
    301     IGnssNiCallback::GnssNiNotification notificationGnss = {};
    302 
    303     notificationGnss.notificationId = id;
    304 
    305     if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
    306         notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
    307     else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
    308         notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
    309     else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
    310         notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
    311     else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
    312         notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
    313 
    314     if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
    315         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
    316     if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
    317         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
    318     if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
    319         notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
    320 
    321     notificationGnss.timeoutSec = gnssNiNotification.timeout;
    322 
    323     if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
    324         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
    325     else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
    326         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
    327     else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
    328             gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
    329         notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
    330 
    331     notificationGnss.requestorId = gnssNiNotification.requestor;
    332 
    333     notificationGnss.notificationMessage = gnssNiNotification.message;
    334 
    335     if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
    336         notificationGnss.requestorIdEncoding =
    337             IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
    338     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
    339         notificationGnss.requestorIdEncoding =
    340             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
    341     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
    342         notificationGnss.requestorIdEncoding =
    343             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
    344     else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
    345         notificationGnss.requestorIdEncoding =
    346             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
    347 
    348     if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
    349         notificationGnss.notificationIdEncoding =
    350             IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
    351     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
    352         notificationGnss.notificationIdEncoding =
    353             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
    354     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
    355         notificationGnss.notificationIdEncoding =
    356             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
    357     else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
    358         notificationGnss.notificationIdEncoding =
    359             IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
    360 
    361     gnssNiCbIface->niNotifyCb(notificationGnss);
    362 }
    363 
    364 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
    365 {
    366     LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
    367     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    368 
    369     if (gnssCbIface != nullptr) {
    370         IGnssCallback::GnssSvStatus svStatus;
    371         convertGnssSvStatus(gnssSvNotification, svStatus);
    372         auto r = gnssCbIface->gnssSvStatusCb(svStatus);
    373         if (!r.isOk()) {
    374             LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
    375                 __func__, r.description().c_str());
    376         }
    377     }
    378 }
    379 
    380 void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
    381 {
    382     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    383 
    384     if (gnssCbIface != nullptr) {
    385         android::hardware::hidl_string nmeaString;
    386         nmeaString.setToExternal(gnssNmeaNotification.nmea, gnssNmeaNotification.length);
    387         auto r = gnssCbIface->gnssNmeaCb(
    388             static_cast<GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
    389         if (!r.isOk()) {
    390             LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s", __func__,
    391                 gnssNmeaNotification.nmea, gnssNmeaNotification.length, r.description().c_str());
    392         }
    393     }
    394 }
    395 
    396 void GnssAPIClient::onStartTrackingCb(LocationError error)
    397 {
    398     LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
    399     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    400 
    401     if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
    402         auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
    403         if (!r.isOk()) {
    404             LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
    405                 __func__, r.description().c_str());
    406         }
    407         r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
    408         if (!r.isOk()) {
    409             LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
    410                 __func__, r.description().c_str());
    411         }
    412     }
    413 }
    414 
    415 void GnssAPIClient::onStopTrackingCb(LocationError error)
    416 {
    417     LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
    418     sp<IGnssCallback> gnssCbIface = mGnssCbIface;
    419 
    420     if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
    421         auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
    422         if (!r.isOk()) {
    423             LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
    424                 __func__, r.description().c_str());
    425         }
    426         r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
    427         if (!r.isOk()) {
    428             LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
    429                 __func__, r.description().c_str());
    430         }
    431     }
    432 }
    433 
    434 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
    435 {
    436     memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
    437     out.numSvs = in.count;
    438     if (out.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
    439         LOC_LOGW("%s]: Too many satellites %zd. Clamps to %d.",
    440                 __FUNCTION__,  out.numSvs, GnssMax::SVS_COUNT);
    441         out.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
    442     }
    443     for (size_t i = 0; i < out.numSvs; i++) {
    444         IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
    445         info.svid = in.gnssSvs[i].svId;
    446         convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
    447         info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
    448         info.elevationDegrees = in.gnssSvs[i].elevation;
    449         info.azimuthDegrees = in.gnssSvs[i].azimuth;
    450         info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
    451         info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
    452         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
    453             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
    454         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
    455             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
    456         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
    457             info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
    458         if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
    459             info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
    460     }
    461 }
    462 
    463 }  // namespace implementation
    464 }  // namespace V1_0
    465 }  // namespace gnss
    466 }  // namespace hardware
    467 }  // namespace android
    468