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