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
LocationAPIClientBase()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
locAPISetCallbacks(LocationCallbacks & locationCallbacks)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
~LocationAPIClientBase()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
locAPIStartTracking(LocationOptions & options)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
locAPIStopTracking()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
locAPIUpdateTrackingOptions(LocationOptions & options)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
locAPIGetBatchSize()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
locAPIStartSession(uint32_t id,uint32_t sessionMode,LocationOptions & options)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
locAPIStopSession(uint32_t id)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
locAPIUpdateSessionOptions(uint32_t id,uint32_t sessionMode,LocationOptions & options)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
locAPIGetBatchedLocations(size_t count)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
locAPIAddGeofences(size_t count,uint32_t * ids,GeofenceOption * options,GeofenceInfo * data)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
locAPIRemoveGeofences(size_t count,uint32_t * ids)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
locAPIModifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)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
locAPIPauseGeofences(size_t count,uint32_t * ids)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
locAPIResumeGeofences(size_t count,uint32_t * ids,GeofenceBreachTypeMask * mask)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
locAPIRemoveAllGeofences()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
locAPIGnssNiResponse(uint32_t id,GnssNiResponse response)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
locAPIGnssDeleteAidingData(GnssAidingData & data)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
locAPIEnable(LocationTechnologyType techType)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
locAPIDisable()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
locAPIGnssUpdateConfig(GnssConfig config)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
beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)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
onResponseCb(LocationError error,uint32_t id)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
onCollectiveResponseCb(size_t count,LocationError * errors,uint32_t * ids)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
onCtrlResponseCb(LocationError error,uint32_t id)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
onCtrlCollectiveResponseCb(size_t count,LocationError * errors,uint32_t * ids)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*
getRequestBySession(uint32_t session)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*
getGeofencesRequest()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