/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation, nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define LOG_TAG "LocSvc_GeofenceAdapter" #include #include "loc_log.h" #include #include using namespace loc_core; GeofenceAdapter::GeofenceAdapter() : LocAdapterBase(0, LocContext::getLocContext( NULL, NULL, LocContext::mLocationHalName, false), true /*isMaster*/) { LOC_LOGD("%s]: Constructor", __func__); } void GeofenceAdapter::stopClientSessions(LocationAPI* client) { LOC_LOGD("%s]: client %p", __func__, client); for (auto it = mGeofenceIds.begin(); it != mGeofenceIds.end();) { uint32_t hwId = it->second; GeofenceKey key(it->first); if (client == key.client) { it = mGeofenceIds.erase(it); mLocApi->removeGeofence(hwId, key.id, new LocApiResponse(*getContext(), [this, hwId] (LocationError err) { if (LOCATION_ERROR_SUCCESS == err) { auto it2 = mGeofences.find(hwId); if (it2 != mGeofences.end()) { mGeofences.erase(it2); } else { LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId); } } })); continue; } ++it; // increment only when not erasing an iterator } } void GeofenceAdapter::updateClientsEventMask() { LOC_API_ADAPTER_EVENT_MASK_T mask = 0; for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { if (it->second.geofenceBreachCb != nullptr) { mask |= LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT; mask |= LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL; } if (it->second.geofenceStatusCb != nullptr) { mask |= LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT; } } updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); } LocationError GeofenceAdapter::getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId) { GeofenceKey key(client, clientId); auto it = mGeofenceIds.find(key); if (it != mGeofenceIds.end()) { hwId = it->second; return LOCATION_ERROR_SUCCESS; } return LOCATION_ERROR_ID_UNKNOWN; } LocationError GeofenceAdapter::getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key) { auto it = mGeofences.find(hwId); if (it != mGeofences.end()) { key = it->second.key; return LOCATION_ERROR_SUCCESS; } return LOCATION_ERROR_ID_UNKNOWN; } void GeofenceAdapter::handleEngineUpEvent() { struct MsgSSREvent : public LocMsg { GeofenceAdapter& mAdapter; inline MsgSSREvent(GeofenceAdapter& adapter) : LocMsg(), mAdapter(adapter) {} virtual void proc() const { mAdapter.setEngineCapabilitiesKnown(true); mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); mAdapter.restartGeofences(); for (auto msg: mAdapter.mPendingMsgs) { mAdapter.sendMsg(msg); } mAdapter.mPendingMsgs.clear(); } }; sendMsg(new MsgSSREvent(*this)); } void GeofenceAdapter::restartGeofences() { if (mGeofences.empty()) { return; } GeofencesMap oldGeofences(mGeofences); mGeofences.clear(); mGeofenceIds.clear(); for (auto it = oldGeofences.begin(); it != oldGeofences.end(); it++) { GeofenceObject object = it->second; GeofenceOption options = {sizeof(GeofenceOption), object.breachMask, object.responsiveness, object.dwellTime}; GeofenceInfo info = {sizeof(GeofenceInfo), object.latitude, object.longitude, object.radius}; mLocApi->addGeofence(object.key.id, options, info, new LocApiResponseData(*getContext(), [this, object, options, info] (LocationError err, LocApiGeofenceData data) { if (LOCATION_ERROR_SUCCESS == err) { if (true == object.paused) { mLocApi->pauseGeofence(data.hwId, object.key.id, new LocApiResponse(*getContext(), [] (LocationError err ) {})); } saveGeofenceItem(object.key.client, object.key.id, data.hwId, options, info); } })); } } void GeofenceAdapter::reportResponse(LocationAPI* client, size_t count, LocationError* errs, uint32_t* ids) { IF_LOC_LOGD { std::string idsString = "["; std::string errsString = "["; if (NULL != ids && NULL != errs) { for (size_t i=0; i < count; ++i) { idsString += std::to_string(ids[i]) + " "; errsString += std::to_string(errs[i]) + " "; } } idsString += "]"; errsString += "]"; LOC_LOGD("%s]: client %p ids %s errs %s", __func__, client, idsString.c_str(), errsString.c_str()); } auto it = mClientData.find(client); if (it != mClientData.end() && it->second.collectiveResponseCb != nullptr) { it->second.collectiveResponseCb(count, errs, ids); } else { LOC_LOGE("%s]: client %p response not found in info", __func__, client); } } uint32_t* GeofenceAdapter::addGeofencesCommand(LocationAPI* client, size_t count, GeofenceOption* options, GeofenceInfo* infos) { LOC_LOGD("%s]: client %p count %zu", __func__, client, count); struct MsgAddGeofences : public LocMsg { GeofenceAdapter& mAdapter; LocApiBase& mApi; LocationAPI* mClient; size_t mCount; uint32_t* mIds; GeofenceOption* mOptions; GeofenceInfo* mInfos; inline MsgAddGeofences(GeofenceAdapter& adapter, LocApiBase& api, LocationAPI* client, size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* infos) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mCount(count), mIds(ids), mOptions(options), mInfos(infos) {} inline virtual void proc() const { LocationError* errs = new LocationError[mCount]; if (nullptr == errs) { LOC_LOGE("%s]: new failed to allocate errs", __func__); return; } for (size_t i=0; i < mCount; ++i) { if (NULL == mIds || NULL == mOptions || NULL == mInfos) { errs[i] = LOCATION_ERROR_INVALID_PARAMETER; } else { mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mOptions = mOptions, mInfos = mInfos, mIds = mIds, &mApi = mApi, errs, i] (LocationError err ) { mApi.addGeofence(mIds[i], mOptions[i], mInfos[i], new LocApiResponseData(*mAdapter.getContext(), [&mAdapter = mAdapter, mOptions = mOptions, mClient = mClient, mCount = mCount, mIds = mIds, mInfos = mInfos, errs, i] (LocationError err, LocApiGeofenceData data) { if (LOCATION_ERROR_SUCCESS == err) { mAdapter.saveGeofenceItem(mClient, mIds[i], data.hwId, mOptions[i], mInfos[i]); } errs[i] = err; // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; delete[] mOptions; delete[] mInfos; } })); })); } } } }; if (0 == count) { return NULL; } uint32_t* ids = new uint32_t[count]; if (nullptr == ids) { LOC_LOGE("%s]: new failed to allocate ids", __func__); return NULL; } if (NULL != ids) { for (size_t i=0; i < count; ++i) { ids[i] = generateSessionId(); } } GeofenceOption* optionsCopy; if (options == NULL) { optionsCopy = NULL; } else { optionsCopy = new GeofenceOption[count]; if (nullptr == optionsCopy) { LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__); return NULL; } COPY_IF_NOT_NULL(optionsCopy, options, count); } GeofenceInfo* infosCopy; if (infos == NULL) { infosCopy = NULL; } else { infosCopy = new GeofenceInfo[count]; if (nullptr == infosCopy) { LOC_LOGE("%s]: new failed to allocate infosCopy", __func__); return NULL; } COPY_IF_NOT_NULL(infosCopy, infos, count); } sendMsg(new MsgAddGeofences(*this, *mLocApi, client, count, ids, optionsCopy, infosCopy)); return ids; } void GeofenceAdapter::removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) { LOC_LOGD("%s]: client %p count %zu", __func__, client, count); struct MsgRemoveGeofences : public LocMsg { GeofenceAdapter& mAdapter; LocApiBase& mApi; LocationAPI* mClient; size_t mCount; uint32_t* mIds; inline MsgRemoveGeofences(GeofenceAdapter& adapter, LocApiBase& api, LocationAPI* client, size_t count, uint32_t* ids) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mCount(count), mIds(ids) {} inline virtual void proc() const { LocationError* errs = new LocationError[mCount]; if (nullptr == errs) { LOC_LOGE("%s]: new failed to allocate errs", __func__); return; } for (size_t i=0; i < mCount; ++i) { mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, &mApi = mApi, errs, i] (LocationError err ) { uint32_t hwId = 0; errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); if (LOCATION_ERROR_SUCCESS == errs[i]) { mApi.removeGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, hwId, errs, i] (LocationError err ) { if (LOCATION_ERROR_SUCCESS == err) { mAdapter.removeGeofenceItem(hwId); } errs[i] = err; // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } })); } else { // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } } })); } } }; if (0 == count) { return; } uint32_t* idsCopy = new uint32_t[count]; if (nullptr == idsCopy) { LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); return; } COPY_IF_NOT_NULL(idsCopy, ids, count); sendMsg(new MsgRemoveGeofences(*this, *mLocApi, client, count, idsCopy)); } void GeofenceAdapter::pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) { LOC_LOGD("%s]: client %p count %zu", __func__, client, count); struct MsgPauseGeofences : public LocMsg { GeofenceAdapter& mAdapter; LocApiBase& mApi; LocationAPI* mClient; size_t mCount; uint32_t* mIds; inline MsgPauseGeofences(GeofenceAdapter& adapter, LocApiBase& api, LocationAPI* client, size_t count, uint32_t* ids) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mCount(count), mIds(ids) {} inline virtual void proc() const { LocationError* errs = new LocationError[mCount]; if (nullptr == errs) { LOC_LOGE("%s]: new failed to allocate errs", __func__); return; } for (size_t i=0; i < mCount; ++i) { mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, &mApi = mApi, errs, i] (LocationError err ) { uint32_t hwId = 0; errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); if (LOCATION_ERROR_SUCCESS == errs[i]) { mApi.pauseGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, hwId, errs, i] (LocationError err ) { if (LOCATION_ERROR_SUCCESS == err) { mAdapter.pauseGeofenceItem(hwId); } errs[i] = err; // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } })); } else { // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } } })); } } }; if (0 == count) { return; } uint32_t* idsCopy = new uint32_t[count]; if (nullptr == idsCopy) { LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); return; } COPY_IF_NOT_NULL(idsCopy, ids, count); sendMsg(new MsgPauseGeofences(*this, *mLocApi, client, count, idsCopy)); } void GeofenceAdapter::resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids) { LOC_LOGD("%s]: client %p count %zu", __func__, client, count); struct MsgResumeGeofences : public LocMsg { GeofenceAdapter& mAdapter; LocApiBase& mApi; LocationAPI* mClient; size_t mCount; uint32_t* mIds; inline MsgResumeGeofences(GeofenceAdapter& adapter, LocApiBase& api, LocationAPI* client, size_t count, uint32_t* ids) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mCount(count), mIds(ids) {} inline virtual void proc() const { LocationError* errs = new LocationError[mCount]; if (nullptr == errs) { LOC_LOGE("%s]: new failed to allocate errs", __func__); return; } for (size_t i=0; i < mCount; ++i) { mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, &mApi = mApi, errs, i] (LocationError err ) { uint32_t hwId = 0; errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); if (LOCATION_ERROR_SUCCESS == errs[i]) { mApi.resumeGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, hwId, errs, mIds = mIds, i] (LocationError err ) { if (LOCATION_ERROR_SUCCESS == err) { errs[i] = err; mAdapter.resumeGeofenceItem(hwId); // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } } })); } else { // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; } } })); } } }; if (0 == count) { return; } uint32_t* idsCopy = new uint32_t[count]; if (nullptr == idsCopy) { LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); return; } COPY_IF_NOT_NULL(idsCopy, ids, count); sendMsg(new MsgResumeGeofences(*this, *mLocApi, client, count, idsCopy)); } void GeofenceAdapter::modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids, GeofenceOption* options) { LOC_LOGD("%s]: client %p count %zu", __func__, client, count); struct MsgModifyGeofences : public LocMsg { GeofenceAdapter& mAdapter; LocApiBase& mApi; LocationAPI* mClient; size_t mCount; uint32_t* mIds; GeofenceOption* mOptions; inline MsgModifyGeofences(GeofenceAdapter& adapter, LocApiBase& api, LocationAPI* client, size_t count, uint32_t* ids, GeofenceOption* options) : LocMsg(), mAdapter(adapter), mApi(api), mClient(client), mCount(count), mIds(ids), mOptions(options) {} inline virtual void proc() const { LocationError* errs = new LocationError[mCount]; if (nullptr == errs) { LOC_LOGE("%s]: new failed to allocate errs", __func__); return; } for (size_t i=0; i < mCount; ++i) { if (NULL == mIds || NULL == mOptions) { errs[i] = LOCATION_ERROR_INVALID_PARAMETER; } else { mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, &mApi = mApi, mOptions = mOptions, errs, i] (LocationError err ) { uint32_t hwId = 0; errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId); if (LOCATION_ERROR_SUCCESS == errs[i]) { mApi.modifyGeofence(hwId, mIds[i], mOptions[i], new LocApiResponse(*mAdapter.getContext(), [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds, mOptions = mOptions, hwId, errs, i] (LocationError err ) { if (LOCATION_ERROR_SUCCESS == err) { errs[i] = err; mAdapter.modifyGeofenceItem(hwId, mOptions[i]); } // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; delete[] mOptions; } })); } else { // Send aggregated response on last item and cleanup if (i == mCount-1) { mAdapter.reportResponse(mClient, mCount, errs, mIds); delete[] errs; delete[] mIds; delete[] mOptions; } } })); } } } }; if (0 == count) { return; } uint32_t* idsCopy = new uint32_t[count]; if (nullptr == idsCopy) { LOC_LOGE("%s]: new failed to allocate idsCopy", __func__); return; } COPY_IF_NOT_NULL(idsCopy, ids, count); GeofenceOption* optionsCopy; if (options == NULL) { optionsCopy = NULL; } else { optionsCopy = new GeofenceOption[count]; if (nullptr == optionsCopy) { LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__); return; } COPY_IF_NOT_NULL(optionsCopy, options, count); } sendMsg(new MsgModifyGeofences(*this, *mLocApi, client, count, idsCopy, optionsCopy)); } void GeofenceAdapter::saveGeofenceItem(LocationAPI* client, uint32_t clientId, uint32_t hwId, const GeofenceOption& options, const GeofenceInfo& info) { LOC_LOGD("%s]: hwId %u client %p clientId %u", __func__, hwId, client, clientId); GeofenceKey key(client, clientId); GeofenceObject object = {key, options.breachTypeMask, options.responsiveness, options.dwellTime, info.latitude, info.longitude, info.radius, false}; mGeofences[hwId] = object; mGeofenceIds[key] = hwId; dump(); } void GeofenceAdapter::removeGeofenceItem(uint32_t hwId) { GeofenceKey key; LocationError err = getGeofenceKeyFromHwId(hwId, key); if (LOCATION_ERROR_SUCCESS != err) { LOC_LOGE("%s]: can not find the key for hwId %u", __func__, hwId); } else { auto it1 = mGeofenceIds.find(key); if (it1 != mGeofenceIds.end()) { mGeofenceIds.erase(it1); auto it2 = mGeofences.find(hwId); if (it2 != mGeofences.end()) { mGeofences.erase(it2); dump(); } else { LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId); } } else { LOC_LOGE("%s]: geofence item to erase not found. hwId %u", __func__, hwId); } } } void GeofenceAdapter::pauseGeofenceItem(uint32_t hwId) { auto it = mGeofences.find(hwId); if (it != mGeofences.end()) { it->second.paused = true; dump(); } else { LOC_LOGE("%s]: geofence item to pause not found. hwId %u", __func__, hwId); } } void GeofenceAdapter::resumeGeofenceItem(uint32_t hwId) { auto it = mGeofences.find(hwId); if (it != mGeofences.end()) { it->second.paused = false; dump(); } else { LOC_LOGE("%s]: geofence item to resume not found. hwId %u", __func__, hwId); } } void GeofenceAdapter::modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options) { auto it = mGeofences.find(hwId); if (it != mGeofences.end()) { it->second.breachMask = options.breachTypeMask; it->second.responsiveness = options.responsiveness; it->second.dwellTime = options.dwellTime; dump(); } else { LOC_LOGE("%s]: geofence item to modify not found. hwId %u", __func__, hwId); } } void GeofenceAdapter::geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location, GeofenceBreachType breachType, uint64_t timestamp) { IF_LOC_LOGD { std::string idsString = "["; if (NULL != hwIds) { for (size_t i=0; i < count; ++i) { idsString += std::to_string(hwIds[i]) + " "; } } idsString += "]"; LOC_LOGD("%s]: breachType %u count %zu ids %s", __func__, breachType, count, idsString.c_str()); } if (0 == count || NULL == hwIds) return; struct MsgGeofenceBreach : public LocMsg { GeofenceAdapter& mAdapter; size_t mCount; uint32_t* mHwIds; Location mLocation; GeofenceBreachType mBreachType; uint64_t mTimestamp; inline MsgGeofenceBreach(GeofenceAdapter& adapter, size_t count, uint32_t* hwIds, Location& location, GeofenceBreachType breachType, uint64_t timestamp) : LocMsg(), mAdapter(adapter), mCount(count), mHwIds(new uint32_t[count]), mLocation(location), mBreachType(breachType), mTimestamp(timestamp) { if (nullptr == mHwIds) { LOC_LOGE("%s]: new failed to allocate mHwIds", __func__); return; } COPY_IF_NOT_NULL(mHwIds, hwIds, mCount); } inline virtual ~MsgGeofenceBreach() { delete[] mHwIds; } inline virtual void proc() const { mAdapter.geofenceBreach(mCount, mHwIds, mLocation, mBreachType, mTimestamp); } }; sendMsg(new MsgGeofenceBreach(*this, count, hwIds, location, breachType, timestamp)); } void GeofenceAdapter::geofenceBreach(size_t count, uint32_t* hwIds, const Location& location, GeofenceBreachType breachType, uint64_t timestamp) { for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { uint32_t* clientIds = new uint32_t[count]; if (nullptr == clientIds) { return; } uint32_t index = 0; for (size_t i=0; i < count; ++i) { GeofenceKey key; LocationError err = getGeofenceKeyFromHwId(hwIds[i], key); if (LOCATION_ERROR_SUCCESS == err) { if (key.client == it->first) { clientIds[index++] = key.id; } } } if (index > 0 && it->second.geofenceBreachCb != nullptr) { GeofenceBreachNotification notify = {sizeof(GeofenceBreachNotification), index, clientIds, location, breachType, timestamp}; it->second.geofenceBreachCb(notify); } delete[] clientIds; } } void GeofenceAdapter::geofenceStatusEvent(GeofenceStatusAvailable available) { LOC_LOGD("%s]: available %u ", __func__, available); struct MsgGeofenceStatus : public LocMsg { GeofenceAdapter& mAdapter; GeofenceStatusAvailable mAvailable; inline MsgGeofenceStatus(GeofenceAdapter& adapter, GeofenceStatusAvailable available) : LocMsg(), mAdapter(adapter), mAvailable(available) {} inline virtual void proc() const { mAdapter.geofenceStatus(mAvailable); } }; sendMsg(new MsgGeofenceStatus(*this, available)); } void GeofenceAdapter::geofenceStatus(GeofenceStatusAvailable available) { for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { if (it->second.geofenceStatusCb != nullptr) { GeofenceStatusNotification notify = {sizeof(GeofenceStatusNotification), available, LOCATION_TECHNOLOGY_TYPE_GNSS}; it->second.geofenceStatusCb(notify); } } } void GeofenceAdapter::dump() { IF_LOC_LOGV { LOC_LOGV( "HAL | hwId | mask | respon | latitude | longitude | radius | paused | Id | client"); for (auto it = mGeofences.begin(); it != mGeofences.end(); ++it) { uint32_t hwId = it->first; GeofenceObject object = it->second; LOC_LOGV(" | %5u | %4u | %6u | %8.2f | %9.2f | %6.2f | %6u | %04x | %p ", hwId, object.breachMask, object.responsiveness, object.latitude, object.longitude, object.radius, object.paused, object.key.id, object.key.client); } } }