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