Home | History | Annotate | Download | only in location
      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 #define LOG_NDDEBUG 0
     30 #define LOG_TAG "LocSvc_APIClientBase"
     31 
     32 #include <platform_lib_log_util.h>
     33 #include <inttypes.h>
     34 #include <loc_cfg.h>
     35 #include "LocationAPIClientBase.h"
     36 
     37 #define FLP_CONF_FILE "/vendor/etc/flp.conf"
     38 #define GEOFENCE_SESSION_ID 0xFFFFFFFF
     39 #define CONFIG_SESSION_ID 0xFFFFFFFF
     40 
     41 // LocationAPIControlClient
     42 LocationAPIControlClient::LocationAPIControlClient() :
     43     mEnabled(false)
     44 {
     45     pthread_mutex_init(&mMutex, nullptr);
     46 
     47     for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
     48         mRequestQueues[i].reset(0);
     49     }
     50 
     51     memset(&mConfig, 0, sizeof(GnssConfig));
     52 
     53     LocationControlCallbacks locationControlCallbacks;
     54     locationControlCallbacks.size = sizeof(LocationControlCallbacks);
     55 
     56     locationControlCallbacks.responseCb =
     57         [this](LocationError error, uint32_t id) {
     58             onCtrlResponseCb(error, id);
     59         };
     60     locationControlCallbacks.collectiveResponseCb =
     61         [this](size_t count, LocationError* errors, uint32_t* ids) {
     62             onCtrlCollectiveResponseCb(count, errors, ids);
     63         };
     64 
     65     mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks);
     66 }
     67 
     68 LocationAPIControlClient::~LocationAPIControlClient()
     69 {
     70     pthread_mutex_lock(&mMutex);
     71 
     72     if (mLocationControlAPI) {
     73         mLocationControlAPI->destroy();
     74         mLocationControlAPI = nullptr;
     75     }
     76 
     77     for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
     78         mRequestQueues[i].reset(0);
     79     }
     80 
     81     pthread_mutex_unlock(&mMutex);
     82 
     83     pthread_mutex_destroy(&mMutex);
     84 }
     85 
     86 uint32_t LocationAPIControlClient::locAPIGnssDeleteAidingData(GnssAidingData& data)
     87 {
     88     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
     89     pthread_mutex_lock(&mMutex);
     90     if (mLocationControlAPI) {
     91         uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data);
     92         LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
     93         mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].reset(session);
     94         mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].push(new GnssDeleteAidingDataRequest(*this));
     95 
     96         retVal = LOCATION_ERROR_SUCCESS;
     97     }
     98     pthread_mutex_unlock(&mMutex);
     99 
    100     return retVal;
    101 }
    102 
    103 uint32_t LocationAPIControlClient::locAPIEnable(LocationTechnologyType techType)
    104 {
    105     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    106     pthread_mutex_lock(&mMutex);
    107     if (mEnabled) {
    108         // just return success if already enabled
    109         retVal = LOCATION_ERROR_SUCCESS;
    110     } else if (mLocationControlAPI) {
    111         uint32_t session = mLocationControlAPI->enable(techType);
    112         LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
    113         mRequestQueues[CTRL_REQUEST_CONTROL].reset(session);
    114         mRequestQueues[CTRL_REQUEST_CONTROL].push(new EnableRequest(*this));
    115         retVal = LOCATION_ERROR_SUCCESS;
    116         mEnabled = true;
    117     } else {
    118         LOC_LOGE("%s:%d] failed.", __FUNCTION__, __LINE__);
    119     }
    120     pthread_mutex_unlock(&mMutex);
    121 
    122     return retVal;
    123 }
    124 
    125 void LocationAPIControlClient::locAPIDisable()
    126 {
    127     pthread_mutex_lock(&mMutex);
    128     if (mEnabled && mLocationControlAPI) {
    129         uint32_t session = 0;
    130         session = mRequestQueues[CTRL_REQUEST_CONTROL].getSession();
    131         if (session > 0) {
    132             mRequestQueues[CTRL_REQUEST_CONTROL].push(new DisableRequest(*this));
    133             mLocationControlAPI->disable(session);
    134             mEnabled = false;
    135         } else {
    136             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
    137         }
    138     }
    139     pthread_mutex_unlock(&mMutex);
    140 }
    141 
    142 uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config)
    143 {
    144     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    145     if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) {
    146         LOC_LOGV("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__);
    147         retVal = LOCATION_ERROR_SUCCESS;
    148         return retVal;
    149     }
    150 
    151     pthread_mutex_lock(&mMutex);
    152     if (mLocationControlAPI) {
    153 
    154         memcpy(&mConfig, &config, sizeof(GnssConfig));
    155 
    156         uint32_t session = 0;
    157         uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
    158         LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray);
    159         if (idArray != nullptr) {
    160             if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() != CONFIG_SESSION_ID) {
    161                 mRequestQueues[CTRL_REQUEST_CONFIG].reset(CONFIG_SESSION_ID);
    162             }
    163             mRequestQueues[CTRL_REQUEST_CONFIG].push(new GnssUpdateConfigRequest(*this));
    164             retVal = LOCATION_ERROR_SUCCESS;
    165         }
    166     }
    167     pthread_mutex_unlock(&mMutex);
    168     return retVal;
    169 }
    170 
    171 void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id)
    172 {
    173     if (error != LOCATION_ERROR_SUCCESS) {
    174         LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
    175     } else {
    176         LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
    177     }
    178     LocationAPIRequest* request = getRequestBySession(id);
    179     if (request) {
    180         request->onResponse(error, id);
    181         delete request;
    182     }
    183 }
    184 
    185 void LocationAPIControlClient::onCtrlCollectiveResponseCb(
    186         size_t count, LocationError* errors, uint32_t* ids)
    187 {
    188     for (size_t i = 0; i < count; i++) {
    189         if (errors[i] != LOCATION_ERROR_SUCCESS) {
    190             LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
    191         } else {
    192             LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
    193         }
    194     }
    195     LocationAPIRequest* request = nullptr;
    196     pthread_mutex_lock(&mMutex);
    197     if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() == CONFIG_SESSION_ID) {
    198         request = mRequestQueues[CTRL_REQUEST_CONFIG].pop();
    199     }
    200     pthread_mutex_unlock(&mMutex);
    201     if (request) {
    202         request->onCollectiveResponse(count, errors, ids);
    203         delete request;
    204     }
    205 }
    206 
    207 LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session)
    208 {
    209     pthread_mutex_lock(&mMutex);
    210     LocationAPIRequest* request = nullptr;
    211     for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
    212         if (i != CTRL_REQUEST_CONFIG &&
    213                 mRequestQueues[i].getSession() == session) {
    214             request = mRequestQueues[i].pop();
    215             break;
    216         }
    217     }
    218     pthread_mutex_unlock(&mMutex);
    219     return request;
    220 }
    221 
    222 // LocationAPIClientBase
    223 LocationAPIClientBase::LocationAPIClientBase() :
    224     mGeofenceBreachCallback(nullptr),
    225     mBatchingStatusCallback(nullptr),
    226     mLocationAPI(nullptr),
    227     mBatchSize(-1),
    228     mTracking(false)
    229 {
    230 
    231     // use recursive mutex, in case callback come from the same thread
    232     pthread_mutexattr_t attr;
    233     pthread_mutexattr_init(&attr);
    234     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    235     pthread_mutex_init(&mMutex, &attr);
    236 
    237     for (int i = 0; i < REQUEST_MAX; i++) {
    238         mRequestQueues[i].reset(0);
    239     }
    240 }
    241 
    242 void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks)
    243 {
    244     pthread_mutex_lock(&mMutex);
    245 
    246     if (locationCallbacks.geofenceBreachCb != nullptr) {
    247         mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb;
    248         locationCallbacks.geofenceBreachCb =
    249             [this](GeofenceBreachNotification geofenceBreachNotification) {
    250                 beforeGeofenceBreachCb(geofenceBreachNotification);
    251             };
    252     }
    253 
    254     locationCallbacks.capabilitiesCb =
    255         [this](LocationCapabilitiesMask capabilitiesMask) {
    256             onCapabilitiesCb(capabilitiesMask);
    257         };
    258     locationCallbacks.responseCb = [this](LocationError error, uint32_t id) {
    259         onResponseCb(error, id);
    260     };
    261     locationCallbacks.collectiveResponseCb =
    262         [this](size_t count, LocationError* errors, uint32_t* ids) {
    263             onCollectiveResponseCb(count, errors, ids);
    264         };
    265 
    266     if (locationCallbacks.batchingStatusCb != nullptr) {
    267         mBatchingStatusCallback = locationCallbacks.batchingStatusCb;
    268         locationCallbacks.batchingStatusCb =
    269             [this](BatchingStatusInfo batchStatus, std::list<uint32_t> & tripCompletedList) {
    270             beforeBatchingStatusCb(batchStatus, tripCompletedList);
    271         };
    272     }
    273 
    274     if (mLocationAPI == nullptr ) {
    275         mLocationAPI = LocationAPI::createInstance(locationCallbacks);
    276     } else {
    277         mLocationAPI->updateCallbacks(locationCallbacks);
    278     }
    279 
    280     pthread_mutex_unlock(&mMutex);
    281 }
    282 
    283 LocationAPIClientBase::~LocationAPIClientBase()
    284 {
    285     pthread_mutex_lock(&mMutex);
    286 
    287     mGeofenceBreachCallback = nullptr;
    288 
    289     if (mLocationAPI) {
    290         mLocationAPI->destroy();
    291         mLocationAPI = nullptr;
    292     }
    293 
    294     for (int i = 0; i < REQUEST_MAX; i++) {
    295         mRequestQueues[i].reset(0);
    296     }
    297 
    298     pthread_mutex_unlock(&mMutex);
    299 
    300     pthread_mutex_destroy(&mMutex);
    301 }
    302 
    303 uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& options)
    304 {
    305     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    306     pthread_mutex_lock(&mMutex);
    307     if (mLocationAPI) {
    308         if (mTracking) {
    309             LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__);
    310         } else {
    311             uint32_t session = mLocationAPI->startTracking(options);
    312             LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
    313             // onResponseCb might be called from other thread immediately after
    314             // startTracking returns, so we are not going to unlock mutex
    315             // until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING]
    316             mRequestQueues[REQUEST_TRACKING].reset(session);
    317             mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
    318             mTracking = true;
    319         }
    320 
    321         retVal = LOCATION_ERROR_SUCCESS;
    322     }
    323     pthread_mutex_unlock(&mMutex);
    324 
    325     return retVal;
    326 }
    327 
    328 void LocationAPIClientBase::locAPIStopTracking()
    329 {
    330     pthread_mutex_lock(&mMutex);
    331     if (mLocationAPI) {
    332         uint32_t session = 0;
    333         session = mRequestQueues[REQUEST_TRACKING].getSession();
    334         if (session > 0) {
    335             mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
    336             mLocationAPI->stopTracking(session);
    337             mTracking = false;
    338         } else {
    339             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
    340         }
    341     }
    342     pthread_mutex_unlock(&mMutex);
    343 }
    344 
    345 void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& options)
    346 {
    347     pthread_mutex_lock(&mMutex);
    348     if (mLocationAPI) {
    349         uint32_t session = 0;
    350         session = mRequestQueues[REQUEST_TRACKING].getSession();
    351         if (session > 0) {
    352             mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
    353             mLocationAPI->updateTrackingOptions(session, options);
    354         } else {
    355             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
    356         }
    357     }
    358     pthread_mutex_unlock(&mMutex);
    359 }
    360 
    361 int32_t LocationAPIClientBase::locAPIGetBatchSize()
    362 {
    363     if (mBatchSize == -1) {
    364         const loc_param_s_type flp_conf_param_table[] =
    365         {
    366             {"BATCH_SIZE", &mBatchSize, nullptr, 'n'},
    367         };
    368         UTIL_READ_CONF(FLP_CONF_FILE, flp_conf_param_table);
    369         if (mBatchSize < 0) {
    370             // set mBatchSize to 0 if we got an illegal value from config file
    371             mBatchSize = 0;
    372         }
    373     }
    374     return mBatchSize;
    375 }
    376 
    377 
    378 uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t sessionMode,
    379         LocationOptions& locationOptions)
    380 {
    381     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    382     pthread_mutex_lock(&mMutex);
    383     if (mLocationAPI) {
    384 
    385         if (mSessionBiDict.hasId(id)) {
    386             LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id);
    387             retVal = LOCATION_ERROR_ALREADY_STARTED;
    388         } else {
    389             uint32_t trackingSession = 0;
    390             uint32_t batchingSession = 0;
    391 
    392             if (sessionMode == SESSION_MODE_ON_FIX) {
    393                 trackingSession = mLocationAPI->startTracking(locationOptions);
    394                 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
    395                 mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
    396             } else if ((sessionMode == SESSION_MODE_ON_FULL) ||
    397                        (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED)) {
    398                 // Fill in the batch mode
    399                 BatchingOptions batchOptions = {};
    400                 batchOptions.size = sizeof(BatchingOptions);
    401                 batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
    402                 if (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
    403                     batchOptions.batchingMode = BATCHING_MODE_TRIP;
    404                 }
    405 
    406                 batchingSession = mLocationAPI->startBatching(locationOptions, batchOptions);
    407                 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
    408                 mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
    409                 mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
    410             }
    411 
    412             uint32_t session = ((sessionMode == SESSION_MODE_ON_FULL ||
    413                     (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED)) ?
    414                     batchingSession : trackingSession);
    415 
    416             SessionEntity entity;
    417             entity.id = id;
    418             entity.trackingSession = trackingSession;
    419             entity.batchingSession = batchingSession;
    420             entity.sessionMode = sessionMode;
    421             mSessionBiDict.set(id, session, entity);
    422 
    423             retVal = LOCATION_ERROR_SUCCESS;
    424         }
    425 
    426     }
    427     pthread_mutex_unlock(&mMutex);
    428 
    429     return retVal;
    430 }
    431 
    432 uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id)
    433 {
    434     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    435     pthread_mutex_lock(&mMutex);
    436     if (mLocationAPI) {
    437 
    438         if (mSessionBiDict.hasId(id)) {
    439             SessionEntity entity = mSessionBiDict.getExtById(id);
    440 
    441             uint32_t trackingSession = entity.trackingSession;
    442             uint32_t batchingSession = entity.batchingSession;
    443             uint32_t sMode = entity.sessionMode;
    444 
    445             if (sMode == SESSION_MODE_ON_FIX) {
    446                 mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this));
    447                 mLocationAPI->stopTracking(trackingSession);
    448             } else if ((sMode == SESSION_MODE_ON_FULL) ||
    449                        (sMode == SESSION_MODE_ON_TRIP_COMPLETED)) {
    450                 mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this));
    451                 mLocationAPI->stopBatching(batchingSession);
    452             } else {
    453                 LOC_LOGE("%s:%d] unknown mode %d.", __FUNCTION__, __LINE__, sMode);
    454             }
    455 
    456             retVal = LOCATION_ERROR_SUCCESS;
    457         } else {
    458             retVal = LOCATION_ERROR_ID_UNKNOWN;
    459             LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
    460         }
    461 
    462     }
    463     pthread_mutex_unlock(&mMutex);
    464     return retVal;
    465 }
    466 
    467 uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode,
    468         LocationOptions& options)
    469 {
    470     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    471     pthread_mutex_lock(&mMutex);
    472     if (mLocationAPI) {
    473 
    474         if (mSessionBiDict.hasId(id)) {
    475             SessionEntity entity = mSessionBiDict.getExtById(id);
    476 
    477             uint32_t trackingSession = entity.trackingSession;
    478             uint32_t batchingSession = entity.batchingSession;
    479             uint32_t sMode = entity.sessionMode;
    480 
    481             if (sessionMode == SESSION_MODE_ON_FIX) {
    482                 // we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION],
    483                 // even if this update request will stop batching and then start tracking.
    484                 mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this));
    485                 if (sMode == SESSION_MODE_ON_FIX) {
    486                     mLocationAPI->updateTrackingOptions(trackingSession, options);
    487                 } else if ((sMode == SESSION_MODE_ON_FULL) ||
    488                            (sMode == SESSION_MODE_ON_TRIP_COMPLETED)) {
    489                     // stop batching
    490                     // batchingSession will be removed from mSessionBiDict soon,
    491                     // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
    492                     mLocationAPI->stopBatching(batchingSession);
    493                     batchingSession = 0;
    494                     mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
    495 
    496                     // start tracking
    497                     trackingSession = mLocationAPI->startTracking(options);
    498                     LOC_LOGI("%s:%d] start new session: %d",
    499                             __FUNCTION__, __LINE__, trackingSession);
    500                 } else {
    501                     LOC_LOGE("%s:%d] unknown mode %d", __FUNCTION__, __LINE__, sMode);
    502                 }
    503             } else if ((sessionMode == SESSION_MODE_ON_FULL) ||
    504                        (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED)) {
    505                 // we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION],
    506                 // even if this update request will stop tracking and then start batching.
    507                 mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this));
    508                 BatchingOptions batchOptions = {};
    509                 batchOptions.size = sizeof(BatchingOptions);
    510                 batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
    511                 if (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
    512                    batchOptions.batchingMode = BATCHING_MODE_TRIP;
    513                 }
    514 
    515                 if (sMode == SESSION_MODE_ON_FIX) {
    516                     // stop tracking
    517                     // trackingSession will be removed from mSessionBiDict soon,
    518                     // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
    519                     mLocationAPI->stopTracking(trackingSession);
    520                     trackingSession = 0;
    521 
    522                     // start batching
    523                     batchingSession = mLocationAPI->startBatching(options, batchOptions);
    524                     LOC_LOGI("%s:%d] start new session: %d",
    525                             __FUNCTION__, __LINE__, batchingSession);
    526                     mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
    527                 } else if ((sMode == SESSION_MODE_ON_FULL) ||
    528                            (sMode == SESSION_MODE_ON_TRIP_COMPLETED)) {
    529                     mLocationAPI->updateBatchingOptions(batchingSession, options, batchOptions);
    530                 } else {
    531                     LOC_LOGE("%s:%d] unknown mode %d", __FUNCTION__, __LINE__, sMode);
    532                 }
    533 
    534             } else {
    535                 LOC_LOGE("%s:%d] unknown mode %d.", __FUNCTION__, __LINE__, sessionMode);
    536             }
    537 
    538             uint32_t session = ((sessionMode == SESSION_MODE_ON_FULL) ||
    539                     (sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) ?
    540                     batchingSession : trackingSession);
    541 
    542             entity.trackingSession = trackingSession;
    543             entity.batchingSession = batchingSession;
    544             entity.sessionMode = sessionMode;
    545             // remove the old values from mSessionBiDict before we add a new one.
    546             mSessionBiDict.rmById(id);
    547             mSessionBiDict.set(id, session, entity);
    548 
    549             retVal = LOCATION_ERROR_SUCCESS;
    550         } else {
    551             retVal = LOCATION_ERROR_ID_UNKNOWN;
    552             LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
    553         }
    554     }
    555     pthread_mutex_unlock(&mMutex);
    556     return retVal;
    557 }
    558 
    559 void LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t count)
    560 {
    561     pthread_mutex_lock(&mMutex);
    562     if (mLocationAPI) {
    563         uint32_t session = 0;
    564         session = mRequestQueues[REQUEST_SESSION].getSession();
    565         if (session > 0) {
    566             SessionEntity entity = mSessionBiDict.getExtById(id);
    567             uint32_t batchingSession = entity.batchingSession;
    568             mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
    569             mLocationAPI->getBatchedLocations(batchingSession, count);
    570         }  else {
    571             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
    572         }
    573     }
    574     pthread_mutex_unlock(&mMutex);
    575 }
    576 
    577 uint32_t LocationAPIClientBase::locAPIAddGeofences(
    578         size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data)
    579 {
    580     uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
    581     pthread_mutex_lock(&mMutex);
    582     if (mLocationAPI) {
    583         if (mRequestQueues[REQUEST_GEOFENCE].getSession() != GEOFENCE_SESSION_ID) {
    584             mRequestQueues[REQUEST_GEOFENCE].reset(GEOFENCE_SESSION_ID);
    585         }
    586         uint32_t* sessions = mLocationAPI->addGeofences(count, options, data);
    587         if (sessions) {
    588             LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions);
    589             mRequestQueues[REQUEST_GEOFENCE].push(new AddGeofencesRequest(*this));
    590 
    591             for (size_t i = 0; i < count; i++) {
    592                 mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
    593             }
    594             retVal = LOCATION_ERROR_SUCCESS;
    595         }
    596     }
    597     pthread_mutex_unlock(&mMutex);
    598 
    599     return retVal;
    600 }
    601 
    602 void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids)
    603 {
    604     pthread_mutex_lock(&mMutex);
    605     if (mLocationAPI) {
    606         uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
    607         if (sessions == NULL) {
    608             LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
    609                     __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
    610             pthread_mutex_unlock(&mMutex);
    611             return;
    612         }
    613 
    614         if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    615             size_t j = 0;
    616             for (size_t i = 0; i < count; i++) {
    617                 sessions[j] = mGeofenceBiDict.getSession(ids[i]);
    618                 if (sessions[j] > 0) {
    619                     j++;
    620                 }
    621             }
    622             if (j > 0) {
    623                 mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this));
    624                 mLocationAPI->removeGeofences(j, sessions);
    625             }
    626         } else {
    627             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
    628                     mRequestQueues[REQUEST_GEOFENCE].getSession());
    629         }
    630 
    631         free(sessions);
    632     }
    633     pthread_mutex_unlock(&mMutex);
    634 }
    635 
    636 void LocationAPIClientBase::locAPIModifyGeofences(
    637         size_t count, uint32_t* ids, GeofenceOption* options)
    638 {
    639     pthread_mutex_lock(&mMutex);
    640     if (mLocationAPI) {
    641         uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
    642         if (sessions == NULL) {
    643             LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
    644                     __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
    645             pthread_mutex_unlock(&mMutex);
    646             return;
    647         }
    648 
    649         if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    650             size_t j = 0;
    651             for (size_t i = 0; i < count; i++) {
    652                 sessions[j] = mGeofenceBiDict.getSession(ids[i]);
    653                 if (sessions[j] > 0) {
    654                     mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask);
    655                     j++;
    656                 }
    657             }
    658             if (j > 0) {
    659                 mRequestQueues[REQUEST_GEOFENCE].push(new ModifyGeofencesRequest(*this));
    660                 mLocationAPI->modifyGeofences(j, sessions, options);
    661             }
    662         } else {
    663             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
    664                     mRequestQueues[REQUEST_GEOFENCE].getSession());
    665         }
    666 
    667         free(sessions);
    668     }
    669     pthread_mutex_unlock(&mMutex);
    670 }
    671 
    672 void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids)
    673 {
    674     pthread_mutex_lock(&mMutex);
    675     if (mLocationAPI) {
    676         uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
    677         if (sessions == NULL) {
    678             LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
    679                     __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
    680             pthread_mutex_unlock(&mMutex);
    681             return;
    682         }
    683 
    684         if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    685             size_t j = 0;
    686             for (size_t i = 0; i < count; i++) {
    687                 sessions[j] = mGeofenceBiDict.getSession(ids[i]);
    688                 if (sessions[j] > 0) {
    689                     j++;
    690                 }
    691             }
    692             if (j > 0) {
    693                 mRequestQueues[REQUEST_GEOFENCE].push(new PauseGeofencesRequest(*this));
    694                 mLocationAPI->pauseGeofences(j, sessions);
    695             }
    696         } else {
    697             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
    698                     mRequestQueues[REQUEST_GEOFENCE].getSession());
    699         }
    700 
    701         free(sessions);
    702     }
    703     pthread_mutex_unlock(&mMutex);
    704 }
    705 
    706 void LocationAPIClientBase::locAPIResumeGeofences(
    707         size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask)
    708 {
    709     pthread_mutex_lock(&mMutex);
    710     if (mLocationAPI) {
    711         uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
    712         if (sessions == NULL) {
    713             LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
    714                     __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
    715             pthread_mutex_unlock(&mMutex);
    716             return;
    717         }
    718 
    719         if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    720             size_t j = 0;
    721             for (size_t i = 0; i < count; i++) {
    722                 sessions[j] = mGeofenceBiDict.getSession(ids[i]);
    723                 if (sessions[j] > 0) {
    724                     if (mask) {
    725                         mGeofenceBiDict.set(ids[i], sessions[j], mask[i]);
    726                     }
    727                     j++;
    728                 }
    729             }
    730             if (j > 0) {
    731                 mRequestQueues[REQUEST_GEOFENCE].push(new ResumeGeofencesRequest(*this));
    732                 mLocationAPI->resumeGeofences(j, sessions);
    733             }
    734         } else {
    735             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
    736                     mRequestQueues[REQUEST_GEOFENCE].getSession());
    737         }
    738 
    739         free(sessions);
    740     }
    741     pthread_mutex_unlock(&mMutex);
    742 }
    743 
    744 void LocationAPIClientBase::locAPIRemoveAllGeofences()
    745 {
    746     pthread_mutex_lock(&mMutex);
    747     if (mLocationAPI) {
    748         std::vector<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions();
    749         size_t count = sessionsVec.size();
    750         uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
    751         if (sessions == NULL) {
    752             LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
    753                     __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
    754             pthread_mutex_unlock(&mMutex);
    755             return;
    756         }
    757 
    758         if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    759             size_t j = 0;
    760             for (size_t i = 0; i < count; i++) {
    761                 sessions[j] = sessionsVec[i];
    762                 if (sessions[j] > 0) {
    763                     j++;
    764                 }
    765             }
    766             if (j > 0) {
    767                 mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this));
    768                 mLocationAPI->removeGeofences(j, sessions);
    769             }
    770         } else {
    771             LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
    772                     mRequestQueues[REQUEST_GEOFENCE].getSession());
    773         }
    774 
    775         free(sessions);
    776     }
    777     pthread_mutex_unlock(&mMutex);
    778 }
    779 
    780 void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
    781 {
    782     pthread_mutex_lock(&mMutex);
    783     if (mLocationAPI) {
    784         uint32_t session = id;
    785         mLocationAPI->gnssNiResponse(id, response);
    786         LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
    787         mRequestQueues[REQUEST_NIRESPONSE].reset(session);
    788         mRequestQueues[REQUEST_NIRESPONSE].push(new GnssNiResponseRequest(*this));
    789     }
    790     pthread_mutex_unlock(&mMutex);
    791 }
    792 
    793 void LocationAPIClientBase::beforeGeofenceBreachCb(
    794         GeofenceBreachNotification geofenceBreachNotification)
    795 {
    796     uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count);
    797     uint32_t* backup = geofenceBreachNotification.ids;
    798     size_t n = geofenceBreachNotification.count;
    799     geofenceBreachCallback genfenceCallback = nullptr;
    800 
    801     if (ids == NULL) {
    802         LOC_LOGE("%s:%d] Failed to alloc %zu bytes",
    803                 __FUNCTION__, __LINE__,
    804                 sizeof(uint32_t) * geofenceBreachNotification.count);
    805         return;
    806     }
    807 
    808     pthread_mutex_lock(&mMutex);
    809     if (mGeofenceBreachCallback != nullptr) {
    810         size_t count = 0;
    811         for (size_t i = 0; i < n; i++) {
    812             uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
    813             GeofenceBreachTypeMask type =
    814                 mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]);
    815             // if type == 0, we will not head into the fllowing block anyway.
    816             // so we don't need to check id and type
    817             if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER &&
    818                         (type & GEOFENCE_BREACH_ENTER_BIT)) ||
    819                     (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT &&
    820                      (type & GEOFENCE_BREACH_EXIT_BIT))
    821                ) {
    822                 ids[count] = id;
    823                 count++;
    824             }
    825         }
    826         geofenceBreachNotification.count = count;
    827         geofenceBreachNotification.ids = ids;
    828 
    829         genfenceCallback = mGeofenceBreachCallback;
    830     }
    831     pthread_mutex_unlock(&mMutex);
    832 
    833     if (genfenceCallback != nullptr) {
    834         genfenceCallback(geofenceBreachNotification);
    835     }
    836 
    837     // restore ids
    838     geofenceBreachNotification.ids = backup;
    839     geofenceBreachNotification.count = n;
    840     free(ids);
    841 }
    842 
    843 void LocationAPIClientBase::beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
    844         std::list<uint32_t> & tripCompletedList) {
    845 
    846     // map the trip ids to the client ids
    847     std::list<uint32_t> tripCompletedClientIdList;
    848     tripCompletedClientIdList.clear();
    849 
    850     if (batchStatus.batchingStatus == BATCHING_STATUS_TRIP_COMPLETED) {
    851         for (auto itt = tripCompletedList.begin(); itt != tripCompletedList.end(); itt++) {
    852             if (mSessionBiDict.hasSession(*itt)) {
    853                 SessionEntity sessEntity = mSessionBiDict.getExtBySession(*itt);
    854 
    855                 if (sessEntity.sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
    856                     tripCompletedClientIdList.push_back(sessEntity.id);
    857                     mSessionBiDict.rmBySession(*itt);
    858                 }
    859             }
    860         }
    861     }
    862 
    863     mBatchingStatusCallback(batchStatus, tripCompletedClientIdList);
    864 }
    865 
    866 void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id)
    867 {
    868     if (error != LOCATION_ERROR_SUCCESS) {
    869         LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
    870     } else {
    871         LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
    872     }
    873     LocationAPIRequest* request = getRequestBySession(id);
    874     if (request) {
    875         request->onResponse(error, id);
    876         delete request;
    877     }
    878 }
    879 
    880 void LocationAPIClientBase::onCollectiveResponseCb(
    881         size_t count, LocationError* errors, uint32_t* ids)
    882 {
    883     for (size_t i = 0; i < count; i++) {
    884         if (errors[i] != LOCATION_ERROR_SUCCESS) {
    885             LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
    886         } else {
    887             LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
    888         }
    889     }
    890     LocationAPIRequest* request = nullptr;
    891     pthread_mutex_lock(&mMutex);
    892     if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
    893         request = mRequestQueues[REQUEST_GEOFENCE].pop();
    894     }
    895     pthread_mutex_unlock(&mMutex);
    896     if (request) {
    897         request->onCollectiveResponse(count, errors, ids);
    898         delete request;
    899     }
    900 }
    901 
    902 void LocationAPIClientBase::removeSession(uint32_t session) {
    903     if (mSessionBiDict.hasSession(session)) {
    904         mSessionBiDict.rmBySession(session);
    905     }
    906 }
    907 
    908 LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session)
    909 {
    910     pthread_mutex_lock(&mMutex);
    911     LocationAPIRequest* request = nullptr;
    912     for (int i = 0; i < REQUEST_MAX; i++) {
    913         if (i != REQUEST_GEOFENCE &&
    914                 i != REQUEST_SESSION &&
    915                 mRequestQueues[i].getSession() == session) {
    916             request = mRequestQueues[i].pop();
    917             break;
    918         }
    919     }
    920     if (request == nullptr) {
    921         // Can't find a request with correct session,
    922         // try to find it from mSessionBiDict
    923         if (mSessionBiDict.hasSession(session)) {
    924             request = mRequestQueues[REQUEST_SESSION].pop();
    925         }
    926     }
    927     pthread_mutex_unlock(&mMutex);
    928     return request;
    929 }
    930