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