1 /* Copyright (c) 2013-2021, 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_TAG "LocSvc_GeofenceAdapter"
30
31 #include <GeofenceAdapter.h>
32 #include "loc_log.h"
33 #include <log_util.h>
34 #include <string>
35
36 using namespace loc_core;
37
GeofenceAdapter()38 GeofenceAdapter::GeofenceAdapter() :
39 LocAdapterBase(0,
40 LocContext::getLocContext(LocContext::mLocationHalName),
41 true /*isMaster*/, nullptr, true)
42 {
43 LOC_LOGD("%s]: Constructor", __func__);
44 // at last step, let us inform adapater base that we are done
45 // with initialization, e.g.: ready to process handleEngineUpEvent
46 doneInit();
47 }
48
49 void
stopClientSessions(LocationAPI * client)50 GeofenceAdapter::stopClientSessions(LocationAPI* client)
51 {
52 LOC_LOGD("%s]: client %p", __func__, client);
53
54
55 for (auto it = mGeofenceIds.begin(); it != mGeofenceIds.end();) {
56 uint32_t hwId = it->second;
57 GeofenceKey key(it->first);
58 if (client == key.client) {
59 it = mGeofenceIds.erase(it);
60 mLocApi->removeGeofence(hwId, key.id,
61 new LocApiResponse(*getContext(),
62 [this, hwId] (LocationError err) {
63 if (LOCATION_ERROR_SUCCESS == err) {
64 auto it2 = mGeofences.find(hwId);
65 if (it2 != mGeofences.end()) {
66 mGeofences.erase(it2);
67 } else {
68 LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId);
69 }
70 }
71 }));
72 continue;
73 }
74 ++it; // increment only when not erasing an iterator
75 }
76
77 }
78
79 void
updateClientsEventMask()80 GeofenceAdapter::updateClientsEventMask()
81 {
82 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
83 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
84 if (it->second.geofenceBreachCb != nullptr) {
85 mask |= LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT;
86 mask |= LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL;
87 }
88 if (it->second.geofenceStatusCb != nullptr) {
89 mask |= LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT;
90 }
91 }
92 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
93 }
94
95 LocationError
getHwIdFromClient(LocationAPI * client,uint32_t clientId,uint32_t & hwId)96 GeofenceAdapter::getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId)
97 {
98 GeofenceKey key(client, clientId);
99 auto it = mGeofenceIds.find(key);
100 if (it != mGeofenceIds.end()) {
101 hwId = it->second;
102 return LOCATION_ERROR_SUCCESS;
103 }
104 return LOCATION_ERROR_ID_UNKNOWN;
105 }
106
107 LocationError
getGeofenceKeyFromHwId(uint32_t hwId,GeofenceKey & key)108 GeofenceAdapter::getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key)
109 {
110 auto it = mGeofences.find(hwId);
111 if (it != mGeofences.end()) {
112 key = it->second.key;
113 return LOCATION_ERROR_SUCCESS;
114 }
115 return LOCATION_ERROR_ID_UNKNOWN;
116 }
117
118 void
handleEngineUpEvent()119 GeofenceAdapter::handleEngineUpEvent()
120 {
121 struct MsgSSREvent : public LocMsg {
122 GeofenceAdapter& mAdapter;
123 inline MsgSSREvent(GeofenceAdapter& adapter) :
124 LocMsg(),
125 mAdapter(adapter) {}
126 virtual void proc() const {
127 mAdapter.setEngineCapabilitiesKnown(true);
128 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
129 mAdapter.restartGeofences();
130 for (auto msg: mAdapter.mPendingMsgs) {
131 mAdapter.sendMsg(msg);
132 }
133 mAdapter.mPendingMsgs.clear();
134 }
135 };
136
137 sendMsg(new MsgSSREvent(*this));
138 }
139
140 void
restartGeofences()141 GeofenceAdapter::restartGeofences()
142 {
143 if (mGeofences.empty()) {
144 return;
145 }
146
147 GeofencesMap oldGeofences(mGeofences);
148 mGeofences.clear();
149 mGeofenceIds.clear();
150
151 for (auto it = oldGeofences.begin(); it != oldGeofences.end(); it++) {
152 GeofenceObject object = it->second;
153 GeofenceOption options = {sizeof(GeofenceOption),
154 object.breachMask,
155 object.responsiveness,
156 object.dwellTime};
157 GeofenceInfo info = {sizeof(GeofenceInfo),
158 object.latitude,
159 object.longitude,
160 object.radius};
161 mLocApi->addGeofence(object.key.id,
162 options,
163 info,
164 new LocApiResponseData<LocApiGeofenceData>(*getContext(),
165 [this, object, options, info] (LocationError err, LocApiGeofenceData data) {
166 if (LOCATION_ERROR_SUCCESS == err) {
167 if (true == object.paused) {
168 mLocApi->pauseGeofence(data.hwId, object.key.id,
169 new LocApiResponse(*getContext(), [] (LocationError err ) {}));
170 }
171 saveGeofenceItem(object.key.client, object.key.id, data.hwId, options, info);
172 }
173 }));
174 }
175 }
176
177 void
reportResponse(LocationAPI * client,size_t count,LocationError * errs,uint32_t * ids)178 GeofenceAdapter::reportResponse(LocationAPI* client, size_t count, LocationError* errs,
179 uint32_t* ids)
180 {
181 IF_LOC_LOGD {
182 std::string idsString = "[";
183 std::string errsString = "[";
184 if (NULL != ids && NULL != errs) {
185 for (size_t i=0; i < count; ++i) {
186 idsString += std::to_string(ids[i]) + " ";
187 errsString += std::to_string(errs[i]) + " ";
188 }
189 }
190 idsString += "]";
191 errsString += "]";
192
193 LOC_LOGD("%s]: client %p ids %s errs %s",
194 __func__, client, idsString.c_str(), errsString.c_str());
195 }
196
197 auto it = mClientData.find(client);
198 if (it != mClientData.end() && it->second.collectiveResponseCb != nullptr) {
199 it->second.collectiveResponseCb(count, errs, ids);
200 } else {
201 LOC_LOGE("%s]: client %p response not found in info", __func__, client);
202 }
203 }
204
205 uint32_t*
addGeofencesCommand(LocationAPI * client,size_t count,GeofenceOption * options,GeofenceInfo * infos)206 GeofenceAdapter::addGeofencesCommand(LocationAPI* client, size_t count, GeofenceOption* options,
207 GeofenceInfo* infos)
208 {
209 LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
210
211 struct MsgAddGeofences : public LocMsg {
212 GeofenceAdapter& mAdapter;
213 LocApiBase& mApi;
214 LocationAPI* mClient;
215 size_t mCount;
216 uint32_t* mIds;
217 GeofenceOption* mOptions;
218 GeofenceInfo* mInfos;
219 inline MsgAddGeofences(GeofenceAdapter& adapter,
220 LocApiBase& api,
221 LocationAPI* client,
222 size_t count,
223 uint32_t* ids,
224 GeofenceOption* options,
225 GeofenceInfo* infos) :
226 LocMsg(),
227 mAdapter(adapter),
228 mApi(api),
229 mClient(client),
230 mCount(count),
231 mIds(ids),
232 mOptions(options),
233 mInfos(infos) {}
234 inline virtual void proc() const {
235 LocationError* errs = new LocationError[mCount];
236 if (nullptr == errs) {
237 LOC_LOGE("%s]: new failed to allocate errs", __func__);
238 return;
239 }
240 for (size_t i=0; i < mCount; ++i) {
241 if (NULL == mIds || NULL == mOptions || NULL == mInfos) {
242 errs[i] = LOCATION_ERROR_INVALID_PARAMETER;
243 } else {
244 mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
245 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient,
246 mOptions = mOptions, mInfos = mInfos, mIds = mIds, &mApi = mApi,
247 errs, i] (LocationError err ) {
248 mApi.addGeofence(mIds[i], mOptions[i], mInfos[i],
249 new LocApiResponseData<LocApiGeofenceData>(*mAdapter.getContext(),
250 [&mAdapter = mAdapter, mOptions = mOptions, mClient = mClient,
251 mCount = mCount, mIds = mIds, mInfos = mInfos, errs, i]
252 (LocationError err, LocApiGeofenceData data) {
253 if (LOCATION_ERROR_SUCCESS == err) {
254 mAdapter.saveGeofenceItem(mClient,
255 mIds[i],
256 data.hwId,
257 mOptions[i],
258 mInfos[i]);
259 }
260 errs[i] = err;
261
262 // Send aggregated response on last item and cleanup
263 if (i == mCount-1) {
264 mAdapter.reportResponse(mClient, mCount, errs, mIds);
265 delete[] errs;
266 delete[] mIds;
267 delete[] mOptions;
268 delete[] mInfos;
269 }
270 }));
271 }));
272 }
273 }
274 }
275 };
276
277 if (0 == count) {
278 return NULL;
279 }
280 uint32_t* ids = new uint32_t[count];
281 if (nullptr == ids) {
282 LOC_LOGE("%s]: new failed to allocate ids", __func__);
283 return NULL;
284 }
285 if (NULL != ids) {
286 for (size_t i=0; i < count; ++i) {
287 ids[i] = generateSessionId();
288 }
289 }
290 GeofenceOption* optionsCopy;
291 if (options == NULL) {
292 optionsCopy = NULL;
293 } else {
294 optionsCopy = new GeofenceOption[count];
295 if (nullptr == optionsCopy) {
296 LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__);
297 return NULL;
298 }
299 COPY_IF_NOT_NULL(optionsCopy, options, count);
300 }
301 GeofenceInfo* infosCopy;
302 if (infos == NULL) {
303 infosCopy = NULL;
304 } else {
305 infosCopy = new GeofenceInfo[count];
306 if (nullptr == infosCopy) {
307 LOC_LOGE("%s]: new failed to allocate infosCopy", __func__);
308 return NULL;
309 }
310 COPY_IF_NOT_NULL(infosCopy, infos, count);
311 }
312
313 sendMsg(new MsgAddGeofences(*this, *mLocApi, client, count, ids, optionsCopy, infosCopy));
314 return ids;
315 }
316
317 void
removeGeofencesCommand(LocationAPI * client,size_t count,uint32_t * ids)318 GeofenceAdapter::removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
319 {
320 LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
321
322 struct MsgRemoveGeofences : public LocMsg {
323 GeofenceAdapter& mAdapter;
324 LocApiBase& mApi;
325 LocationAPI* mClient;
326 size_t mCount;
327 uint32_t* mIds;
328 inline MsgRemoveGeofences(GeofenceAdapter& adapter,
329 LocApiBase& api,
330 LocationAPI* client,
331 size_t count,
332 uint32_t* ids) :
333 LocMsg(),
334 mAdapter(adapter),
335 mApi(api),
336 mClient(client),
337 mCount(count),
338 mIds(ids) {}
339 inline virtual void proc() const {
340 LocationError* errs = new LocationError[mCount];
341 if (nullptr == errs) {
342 LOC_LOGE("%s]: new failed to allocate errs", __func__);
343 return;
344 }
345 for (size_t i=0; i < mCount; ++i) {
346 mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
347 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
348 &mApi = mApi, errs, i] (LocationError err ) {
349 uint32_t hwId = 0;
350 errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
351 if (LOCATION_ERROR_SUCCESS == errs[i]) {
352 mApi.removeGeofence(hwId, mIds[i],
353 new LocApiResponse(*mAdapter.getContext(),
354 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
355 hwId, errs, i] (LocationError err ) {
356 if (LOCATION_ERROR_SUCCESS == err) {
357 mAdapter.removeGeofenceItem(hwId);
358 }
359 errs[i] = err;
360
361 // Send aggregated response on last item and cleanup
362 if (i == mCount-1) {
363 mAdapter.reportResponse(mClient, mCount, errs, mIds);
364 delete[] errs;
365 delete[] mIds;
366 }
367 }));
368 } else {
369 // Send aggregated response on last item and cleanup
370 if (i == mCount-1) {
371 mAdapter.reportResponse(mClient, mCount, errs, mIds);
372 delete[] errs;
373 delete[] mIds;
374 }
375 }
376 }));
377 }
378 }
379 };
380
381 if (0 == count) {
382 return;
383 }
384 uint32_t* idsCopy = new uint32_t[count];
385 if (nullptr == idsCopy) {
386 LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
387 return;
388 }
389 COPY_IF_NOT_NULL(idsCopy, ids, count);
390 sendMsg(new MsgRemoveGeofences(*this, *mLocApi, client, count, idsCopy));
391 }
392
393 void
pauseGeofencesCommand(LocationAPI * client,size_t count,uint32_t * ids)394 GeofenceAdapter::pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
395 {
396 LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
397
398 struct MsgPauseGeofences : public LocMsg {
399 GeofenceAdapter& mAdapter;
400 LocApiBase& mApi;
401 LocationAPI* mClient;
402 size_t mCount;
403 uint32_t* mIds;
404 inline MsgPauseGeofences(GeofenceAdapter& adapter,
405 LocApiBase& api,
406 LocationAPI* client,
407 size_t count,
408 uint32_t* ids) :
409 LocMsg(),
410 mAdapter(adapter),
411 mApi(api),
412 mClient(client),
413 mCount(count),
414 mIds(ids) {}
415 inline virtual void proc() const {
416 LocationError* errs = new LocationError[mCount];
417 if (nullptr == errs) {
418 LOC_LOGE("%s]: new failed to allocate errs", __func__);
419 return;
420 }
421 for (size_t i=0; i < mCount; ++i) {
422 mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
423 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
424 &mApi = mApi, errs, i] (LocationError err ) {
425 uint32_t hwId = 0;
426 errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
427 if (LOCATION_ERROR_SUCCESS == errs[i]) {
428 mApi.pauseGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(),
429 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
430 hwId, errs, i] (LocationError err ) {
431 if (LOCATION_ERROR_SUCCESS == err) {
432 mAdapter.pauseGeofenceItem(hwId);
433 }
434 errs[i] = err;
435
436 // Send aggregated response on last item and cleanup
437 if (i == mCount-1) {
438 mAdapter.reportResponse(mClient, mCount, errs, mIds);
439 delete[] errs;
440 delete[] mIds;
441 }
442 }));
443 } else {
444 // Send aggregated response on last item and cleanup
445 if (i == mCount-1) {
446 mAdapter.reportResponse(mClient, mCount, errs, mIds);
447 delete[] errs;
448 delete[] mIds;
449 }
450 }
451 }));
452 }
453 }
454 };
455
456 if (0 == count) {
457 return;
458 }
459 uint32_t* idsCopy = new uint32_t[count];
460 if (nullptr == idsCopy) {
461 LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
462 return;
463 }
464 COPY_IF_NOT_NULL(idsCopy, ids, count);
465 sendMsg(new MsgPauseGeofences(*this, *mLocApi, client, count, idsCopy));
466 }
467
468 void
resumeGeofencesCommand(LocationAPI * client,size_t count,uint32_t * ids)469 GeofenceAdapter::resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
470 {
471 LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
472
473 struct MsgResumeGeofences : public LocMsg {
474 GeofenceAdapter& mAdapter;
475 LocApiBase& mApi;
476 LocationAPI* mClient;
477 size_t mCount;
478 uint32_t* mIds;
479 inline MsgResumeGeofences(GeofenceAdapter& adapter,
480 LocApiBase& api,
481 LocationAPI* client,
482 size_t count,
483 uint32_t* ids) :
484 LocMsg(),
485 mAdapter(adapter),
486 mApi(api),
487 mClient(client),
488 mCount(count),
489 mIds(ids) {}
490 inline virtual void proc() const {
491 LocationError* errs = new LocationError[mCount];
492 if (nullptr == errs) {
493 LOC_LOGE("%s]: new failed to allocate errs", __func__);
494 return;
495 }
496 for (size_t i=0; i < mCount; ++i) {
497 mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
498 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
499 &mApi = mApi, errs, i] (LocationError err ) {
500 uint32_t hwId = 0;
501 errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
502 if (LOCATION_ERROR_SUCCESS == errs[i]) {
503 mApi.resumeGeofence(hwId, mIds[i],
504 new LocApiResponse(*mAdapter.getContext(),
505 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, hwId,
506 errs, mIds = mIds, i] (LocationError err ) {
507 if (LOCATION_ERROR_SUCCESS == err) {
508 errs[i] = err;
509
510 mAdapter.resumeGeofenceItem(hwId);
511 // Send aggregated response on last item and cleanup
512 if (i == mCount-1) {
513 mAdapter.reportResponse(mClient, mCount, errs, mIds);
514 delete[] errs;
515 delete[] mIds;
516 }
517 }
518 }));
519 } else {
520 // Send aggregated response on last item and cleanup
521 if (i == mCount-1) {
522 mAdapter.reportResponse(mClient, mCount, errs, mIds);
523 delete[] errs;
524 delete[] mIds;
525 }
526 }
527 }));
528 }
529 }
530 };
531
532 if (0 == count) {
533 return;
534 }
535 uint32_t* idsCopy = new uint32_t[count];
536 if (nullptr == idsCopy) {
537 LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
538 return;
539 }
540 COPY_IF_NOT_NULL(idsCopy, ids, count);
541 sendMsg(new MsgResumeGeofences(*this, *mLocApi, client, count, idsCopy));
542 }
543
544 void
modifyGeofencesCommand(LocationAPI * client,size_t count,uint32_t * ids,GeofenceOption * options)545 GeofenceAdapter::modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids,
546 GeofenceOption* options)
547 {
548 LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
549
550 struct MsgModifyGeofences : public LocMsg {
551 GeofenceAdapter& mAdapter;
552 LocApiBase& mApi;
553 LocationAPI* mClient;
554 size_t mCount;
555 uint32_t* mIds;
556 GeofenceOption* mOptions;
557 inline MsgModifyGeofences(GeofenceAdapter& adapter,
558 LocApiBase& api,
559 LocationAPI* client,
560 size_t count,
561 uint32_t* ids,
562 GeofenceOption* options) :
563 LocMsg(),
564 mAdapter(adapter),
565 mApi(api),
566 mClient(client),
567 mCount(count),
568 mIds(ids),
569 mOptions(options) {}
570 inline virtual void proc() const {
571 LocationError* errs = new LocationError[mCount];
572 if (nullptr == errs) {
573 LOC_LOGE("%s]: new failed to allocate errs", __func__);
574 return;
575 }
576 for (size_t i=0; i < mCount; ++i) {
577 if (NULL == mIds || NULL == mOptions) {
578 errs[i] = LOCATION_ERROR_INVALID_PARAMETER;
579 } else {
580 mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
581 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
582 &mApi = mApi, mOptions = mOptions, errs, i] (LocationError err ) {
583 uint32_t hwId = 0;
584 errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
585 if (LOCATION_ERROR_SUCCESS == errs[i]) {
586 mApi.modifyGeofence(hwId, mIds[i], mOptions[i],
587 new LocApiResponse(*mAdapter.getContext(),
588 [&mAdapter = mAdapter, mCount = mCount, mClient = mClient,
589 mIds = mIds, mOptions = mOptions, hwId, errs, i]
590 (LocationError err ) {
591 if (LOCATION_ERROR_SUCCESS == err) {
592 errs[i] = err;
593
594 mAdapter.modifyGeofenceItem(hwId, mOptions[i]);
595 }
596 // Send aggregated response on last item and cleanup
597 if (i == mCount-1) {
598 mAdapter.reportResponse(mClient, mCount, errs, mIds);
599 delete[] errs;
600 delete[] mIds;
601 delete[] mOptions;
602 }
603 }));
604 } else {
605 // Send aggregated response on last item and cleanup
606 if (i == mCount-1) {
607 mAdapter.reportResponse(mClient, mCount, errs, mIds);
608 delete[] errs;
609 delete[] mIds;
610 delete[] mOptions;
611 }
612 }
613 }));
614 }
615 }
616 }
617 };
618
619 if (0 == count) {
620 return;
621 }
622 uint32_t* idsCopy = new uint32_t[count];
623 if (nullptr == idsCopy) {
624 LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
625 return;
626 }
627 COPY_IF_NOT_NULL(idsCopy, ids, count);
628 GeofenceOption* optionsCopy;
629 if (options == NULL) {
630 optionsCopy = NULL;
631 } else {
632 optionsCopy = new GeofenceOption[count];
633 if (nullptr == optionsCopy) {
634 LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__);
635 return;
636 }
637 COPY_IF_NOT_NULL(optionsCopy, options, count);
638 }
639
640 sendMsg(new MsgModifyGeofences(*this, *mLocApi, client, count, idsCopy, optionsCopy));
641 }
642
643 void
saveGeofenceItem(LocationAPI * client,uint32_t clientId,uint32_t hwId,const GeofenceOption & options,const GeofenceInfo & info)644 GeofenceAdapter::saveGeofenceItem(LocationAPI* client, uint32_t clientId, uint32_t hwId,
645 const GeofenceOption& options, const GeofenceInfo& info)
646 {
647 LOC_LOGD("%s]: hwId %u client %p clientId %u", __func__, hwId, client, clientId);
648 GeofenceKey key(client, clientId);
649 GeofenceObject object = {key,
650 options.breachTypeMask,
651 options.responsiveness,
652 options.dwellTime,
653 info.latitude,
654 info.longitude,
655 info.radius,
656 false};
657 mGeofences[hwId] = object;
658 mGeofenceIds[key] = hwId;
659 dump();
660 }
661
662 void
removeGeofenceItem(uint32_t hwId)663 GeofenceAdapter::removeGeofenceItem(uint32_t hwId)
664 {
665 GeofenceKey key;
666 LocationError err = getGeofenceKeyFromHwId(hwId, key);
667 if (LOCATION_ERROR_SUCCESS != err) {
668 LOC_LOGE("%s]: can not find the key for hwId %u", __func__, hwId);
669 } else {
670 auto it1 = mGeofenceIds.find(key);
671 if (it1 != mGeofenceIds.end()) {
672 mGeofenceIds.erase(it1);
673
674 auto it2 = mGeofences.find(hwId);
675 if (it2 != mGeofences.end()) {
676 mGeofences.erase(it2);
677 dump();
678 } else {
679 LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId);
680 }
681 } else {
682 LOC_LOGE("%s]: geofence item to erase not found. hwId %u", __func__, hwId);
683 }
684 }
685 }
686
687 void
pauseGeofenceItem(uint32_t hwId)688 GeofenceAdapter::pauseGeofenceItem(uint32_t hwId)
689 {
690 auto it = mGeofences.find(hwId);
691 if (it != mGeofences.end()) {
692 it->second.paused = true;
693 dump();
694 } else {
695 LOC_LOGE("%s]: geofence item to pause not found. hwId %u", __func__, hwId);
696 }
697 }
698
699 void
resumeGeofenceItem(uint32_t hwId)700 GeofenceAdapter::resumeGeofenceItem(uint32_t hwId)
701 {
702 auto it = mGeofences.find(hwId);
703 if (it != mGeofences.end()) {
704 it->second.paused = false;
705 dump();
706 } else {
707 LOC_LOGE("%s]: geofence item to resume not found. hwId %u", __func__, hwId);
708 }
709 }
710
711 void
modifyGeofenceItem(uint32_t hwId,const GeofenceOption & options)712 GeofenceAdapter::modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options)
713 {
714 auto it = mGeofences.find(hwId);
715 if (it != mGeofences.end()) {
716 it->second.breachMask = options.breachTypeMask;
717 it->second.responsiveness = options.responsiveness;
718 it->second.dwellTime = options.dwellTime;
719 dump();
720 } else {
721 LOC_LOGE("%s]: geofence item to modify not found. hwId %u", __func__, hwId);
722 }
723 }
724
725
726 void
geofenceBreachEvent(size_t count,uint32_t * hwIds,Location & location,GeofenceBreachType breachType,uint64_t timestamp)727 GeofenceAdapter::geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location,
728 GeofenceBreachType breachType, uint64_t timestamp)
729 {
730
731 IF_LOC_LOGD {
732 std::string idsString = "[";
733 if (NULL != hwIds) {
734 for (size_t i=0; i < count; ++i) {
735 idsString += std::to_string(hwIds[i]) + " ";
736 }
737 }
738 idsString += "]";
739 LOC_LOGD("%s]: breachType %u count %zu ids %s",
740 __func__, breachType, count, idsString.c_str());
741 }
742
743 if (0 == count || NULL == hwIds)
744 return;
745
746 struct MsgGeofenceBreach : public LocMsg {
747 GeofenceAdapter& mAdapter;
748 size_t mCount;
749 uint32_t* mHwIds;
750 Location mLocation;
751 GeofenceBreachType mBreachType;
752 uint64_t mTimestamp;
753 inline MsgGeofenceBreach(GeofenceAdapter& adapter,
754 size_t count,
755 uint32_t* hwIds,
756 Location& location,
757 GeofenceBreachType breachType,
758 uint64_t timestamp) :
759 LocMsg(),
760 mAdapter(adapter),
761 mCount(count),
762 mHwIds(new uint32_t[count]),
763 mLocation(location),
764 mBreachType(breachType),
765 mTimestamp(timestamp)
766 {
767 if (nullptr == mHwIds) {
768 LOC_LOGE("%s]: new failed to allocate mHwIds", __func__);
769 return;
770 }
771 COPY_IF_NOT_NULL(mHwIds, hwIds, mCount);
772 }
773 inline virtual ~MsgGeofenceBreach() {
774 delete[] mHwIds;
775 }
776 inline virtual void proc() const {
777 mAdapter.geofenceBreach(mCount, mHwIds, mLocation, mBreachType, mTimestamp);
778 }
779 };
780
781 sendMsg(new MsgGeofenceBreach(*this, count, hwIds, location, breachType, timestamp));
782
783 }
784
785 void
geofenceBreach(size_t count,uint32_t * hwIds,const Location & location,GeofenceBreachType breachType,uint64_t timestamp)786 GeofenceAdapter::geofenceBreach(size_t count, uint32_t* hwIds, const Location& location,
787 GeofenceBreachType breachType, uint64_t timestamp)
788 {
789
790 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
791 uint32_t* clientIds = new uint32_t[count];
792 if (nullptr == clientIds) {
793 return;
794 }
795 uint32_t index = 0;
796 for (size_t i=0; i < count; ++i) {
797 GeofenceKey key;
798 LocationError err = getGeofenceKeyFromHwId(hwIds[i], key);
799 if (LOCATION_ERROR_SUCCESS == err) {
800 if (key.client == it->first) {
801 clientIds[index++] = key.id;
802 }
803 }
804 }
805 if (index > 0 && it->second.geofenceBreachCb != nullptr) {
806 GeofenceBreachNotification notify = {sizeof(GeofenceBreachNotification),
807 index,
808 clientIds,
809 location,
810 breachType,
811 timestamp};
812
813 it->second.geofenceBreachCb(notify);
814 }
815 delete[] clientIds;
816 }
817 }
818
819 void
geofenceStatusEvent(GeofenceStatusAvailable available)820 GeofenceAdapter::geofenceStatusEvent(GeofenceStatusAvailable available)
821 {
822 LOC_LOGD("%s]: available %u ", __func__, available);
823
824 struct MsgGeofenceStatus : public LocMsg {
825 GeofenceAdapter& mAdapter;
826 GeofenceStatusAvailable mAvailable;
827 inline MsgGeofenceStatus(GeofenceAdapter& adapter,
828 GeofenceStatusAvailable available) :
829 LocMsg(),
830 mAdapter(adapter),
831 mAvailable(available) {}
832 inline virtual void proc() const {
833 mAdapter.geofenceStatus(mAvailable);
834 }
835 };
836
837 sendMsg(new MsgGeofenceStatus(*this, available));
838 }
839
840 void
geofenceStatus(GeofenceStatusAvailable available)841 GeofenceAdapter::geofenceStatus(GeofenceStatusAvailable available)
842 {
843 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
844 if (it->second.geofenceStatusCb != nullptr) {
845 GeofenceStatusNotification notify = {sizeof(GeofenceStatusNotification),
846 available,
847 LOCATION_TECHNOLOGY_TYPE_GNSS};
848 it->second.geofenceStatusCb(notify);
849 }
850 }
851 }
852
853 void
dump()854 GeofenceAdapter::dump()
855 {
856 IF_LOC_LOGV {
857 LOC_LOGV(
858 "HAL | hwId | mask | respon | latitude | longitude | radius | paused | Id | client");
859 for (auto it = mGeofences.begin(); it != mGeofences.end(); ++it) {
860 uint32_t hwId = it->first;
861 GeofenceObject object = it->second;
862 LOC_LOGV(" | %5u | %4u | %6u | %8.2f | %9.2f | %6.2f | %6u | %04x | %p ",
863 hwId, object.breachMask, object.responsiveness,
864 object.latitude, object.longitude, object.radius,
865 object.paused, object.key.id, object.key.client);
866 }
867 }
868 }
869
870