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