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