• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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 
~LocationAPIControlClient()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 
locAPIGnssDeleteAidingData(GnssAidingData & data)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 
locAPIEnable(LocationTechnologyType techType)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 
locAPIDisable()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 
locAPIGnssUpdateConfig(GnssConfig config)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 
onCtrlResponseCb(LocationError error,uint32_t id)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 
onCtrlCollectiveResponseCb(size_t count,LocationError * errors,uint32_t * ids)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 
getRequestBySession(uint32_t session)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
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 
locAPISetCallbacks(LocationCallbacks & locationCallbacks)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 
~LocationAPIClientBase()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 
locAPIStartTracking(LocationOptions & options)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 
locAPIStopTracking()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 
locAPIUpdateTrackingOptions(LocationOptions & options)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 
locAPIGetBatchSize()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 
locAPIStartSession(uint32_t id,uint32_t sessionMode,LocationOptions & locationOptions)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 
locAPIStopSession(uint32_t id)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 
locAPIUpdateSessionOptions(uint32_t id,uint32_t sessionMode,LocationOptions & options)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 
locAPIGetBatchedLocations(uint32_t id,size_t count)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 
locAPIAddGeofences(size_t count,uint32_t * ids,GeofenceOption * options,GeofenceInfo * data)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 
locAPIRemoveGeofences(size_t count,uint32_t * ids)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 
locAPIModifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)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 
locAPIPauseGeofences(size_t count,uint32_t * ids)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 
locAPIResumeGeofences(size_t count,uint32_t * ids,GeofenceBreachTypeMask * mask)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 
locAPIRemoveAllGeofences()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 
locAPIGnssNiResponse(uint32_t id,GnssNiResponse response)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 
beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)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 
beforeBatchingStatusCb(BatchingStatusInfo batchStatus,std::list<uint32_t> & tripCompletedList)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 
onResponseCb(LocationError error,uint32_t id)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 
onCollectiveResponseCb(size_t count,LocationError * errors,uint32_t * ids)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 
removeSession(uint32_t session)902 void LocationAPIClientBase::removeSession(uint32_t session) {
903     if (mSessionBiDict.hasSession(session)) {
904         mSessionBiDict.rmBySession(session);
905     }
906 }
907 
getRequestBySession(uint32_t session)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