3094f39138
Change-Id: I0acef3da2c3567a28edd0a71dac89a5828f7725d
985 lines
36 KiB
C++
985 lines
36 KiB
C++
/* Copyright (c) 2013-2021, 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.
|
|
*
|
|
*/
|
|
/*
|
|
Changes from Qualcomm Innovation Center are provided under the following license:
|
|
|
|
Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted (subject to the limitations in the
|
|
disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
|
|
contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
|
|
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
|
|
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <GeofenceAdapter.h>
|
|
#include "loc_log.h"
|
|
#include <log_util.h>
|
|
#include <string>
|
|
|
|
using namespace loc_core;
|
|
|
|
GeofenceAdapter::GeofenceAdapter() :
|
|
LocAdapterBase(0,
|
|
LocContext::getLocContext(LocContext::mLocationHalName),
|
|
true /*isMaster*/, nullptr, true),
|
|
mSystemPowerState(POWER_STATE_UNKNOWN)
|
|
{
|
|
LOC_LOGD("%s]: Constructor", __func__);
|
|
|
|
// at last step, let us inform adapater base that we are done
|
|
// with initialization, e.g.: ready to process handleEngineUpEvent
|
|
doneInit();
|
|
}
|
|
|
|
void
|
|
GeofenceAdapter::stopClientSessions(LocationAPI* client, bool eraseSession)
|
|
{
|
|
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) {
|
|
if (eraseSession)
|
|
it = mGeofenceIds.erase(it);
|
|
mLocApi->removeGeofence(hwId, key.id,
|
|
new LocApiResponse(*getContext(),
|
|
[this, hwId, eraseSession] (LocationError err) {
|
|
if (LOCATION_ERROR_SUCCESS == err) {
|
|
auto it2 = mGeofences.find(hwId);
|
|
if (it2 != mGeofences.end()) {
|
|
if (eraseSession)
|
|
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());
|
|
if ((POWER_STATE_SUSPEND != mAdapter.mSystemPowerState) &&
|
|
POWER_STATE_SHUTDOWN != mAdapter.mSystemPowerState) {
|
|
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,
|
|
object.confidence};
|
|
GeofenceInfo info = {sizeof(GeofenceInfo),
|
|
object.latitude,
|
|
object.longitude,
|
|
object.radius};
|
|
mLocApi->addGeofence(object.key.id,
|
|
options,
|
|
info,
|
|
new LocApiResponseData<LocApiGeofenceData>(*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 __unused) {}));
|
|
}
|
|
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 __unused) {
|
|
mApi.addGeofence(mIds[i], mOptions[i], mInfos[i],
|
|
new LocApiResponseData<LocApiGeofenceData>(*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 __unused) {
|
|
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 __unused) {
|
|
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 __unused) {
|
|
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 __unused) {
|
|
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,
|
|
options.confidence,
|
|
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;
|
|
it->second.confidence = options.confidence;
|
|
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::updateSystemPowerStateCommand(PowerStateType powerState)
|
|
{
|
|
LOC_LOGD("%s]: powerState: %d", __func__, powerState);
|
|
|
|
struct MsgUpdateSystemPowerState : public LocMsg {
|
|
GeofenceAdapter& mAdapter;
|
|
PowerStateType mPowerState;
|
|
inline MsgUpdateSystemPowerState(GeofenceAdapter& adapter,
|
|
PowerStateType powerState) :
|
|
mAdapter(adapter),
|
|
mPowerState(powerState) {}
|
|
inline virtual void proc() const {
|
|
mAdapter.updateSystemPowerState(mPowerState);
|
|
}
|
|
};
|
|
|
|
sendMsg(new MsgUpdateSystemPowerState(*this, powerState));
|
|
}
|
|
|
|
|
|
void
|
|
GeofenceAdapter::pauseOrResumeGeofences(bool pauseOrResume /*false - pause, true - resume*/)
|
|
{
|
|
for (auto it = mGeofenceIds.begin(); it != mGeofenceIds.end(); ++it) {
|
|
|
|
uint32_t hwId = it->second;
|
|
if (false == pauseOrResume) {
|
|
mLocApi->pauseGeofence(it->second, it->first.id, new LocApiResponse(*getContext(),
|
|
[&mAdapter = *this, hwId = hwId] (LocationError err) {
|
|
if (LOCATION_ERROR_SUCCESS == err) {
|
|
mAdapter.pauseGeofenceItem(hwId);
|
|
}
|
|
}));
|
|
} else {
|
|
mLocApi->resumeGeofence(it->second, it->first.id, new LocApiResponse(*getContext(),
|
|
[&mAdapter = *this, hwId = hwId] (LocationError err) {
|
|
if (LOCATION_ERROR_SUCCESS == err) {
|
|
mAdapter.resumeGeofenceItem(hwId);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
GeofenceAdapter::updateSystemPowerState(PowerStateType systemPowerState)
|
|
{
|
|
|
|
if (POWER_STATE_UNKNOWN != systemPowerState) {
|
|
mSystemPowerState = systemPowerState;
|
|
|
|
/*Manage active GNSS sessions based on power event*/
|
|
switch (systemPowerState){
|
|
|
|
case POWER_STATE_SUSPEND:
|
|
case POWER_STATE_SHUTDOWN:
|
|
pauseOrResumeGeofences(false /*pause*/);
|
|
LOC_LOGd("Pause all geoFences -- powerState: %d", systemPowerState);
|
|
break;
|
|
case POWER_STATE_RESUME:
|
|
pauseOrResumeGeofences(true /*resume*/);
|
|
LOC_LOGd("Resume all geoFences -- powerState: %d", systemPowerState);
|
|
break;
|
|
default:
|
|
break;
|
|
} // switch
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|