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