You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
7.5 KiB
225 lines
7.5 KiB
/* |
|
* Copyright (C) 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#define LOG_TAG "GnssHal_GnssGeofencing" |
|
|
|
#include "GnssGeofencing.h" |
|
#include <GnssUtils.h> |
|
|
|
namespace android { |
|
namespace hardware { |
|
namespace gnss { |
|
namespace V1_0 { |
|
namespace implementation { |
|
|
|
std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList; |
|
sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr; |
|
bool GnssGeofencing::sInterfaceExists = false; |
|
|
|
GpsGeofenceCallbacks GnssGeofencing::sGnssGfCb = { |
|
.geofence_transition_callback = gnssGfTransitionCb, |
|
.geofence_status_callback = gnssGfStatusCb, |
|
.geofence_add_callback = gnssGfAddCb, |
|
.geofence_remove_callback = gnssGfRemoveCb, |
|
.geofence_pause_callback = gnssGfPauseCb, |
|
.geofence_resume_callback = gnssGfResumeCb, |
|
.create_thread_cb = createThreadCb |
|
}; |
|
|
|
GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface) |
|
: mGnssGeofencingIface(gpsGeofencingIface) { |
|
/* Error out if an instance of the interface already exists. */ |
|
LOG_ALWAYS_FATAL_IF(sInterfaceExists); |
|
sInterfaceExists = true; |
|
} |
|
|
|
GnssGeofencing::~GnssGeofencing() { |
|
sThreadFuncArgsList.clear(); |
|
sInterfaceExists = false; |
|
} |
|
void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId, |
|
GpsLocation* location, |
|
int32_t transition, |
|
GpsUtcTime timestamp) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
if (location == nullptr) { |
|
ALOGE("%s : Invalid location from GNSS HAL", __func__); |
|
return; |
|
} |
|
|
|
GnssLocation gnssLocation = convertToGnssLocation(location); |
|
auto ret = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( |
|
geofenceId, |
|
gnssLocation, |
|
static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition), |
|
timestamp); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation* location) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
GnssLocation gnssLocation; |
|
|
|
if (location != nullptr) { |
|
gnssLocation = convertToGnssLocation(location); |
|
} else { |
|
gnssLocation = {}; |
|
} |
|
|
|
auto ret = mGnssGeofencingCbIface->gnssGeofenceStatusCb( |
|
static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
auto ret = mGnssGeofencingCbIface->gnssGeofenceAddCb( |
|
geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
auto ret = mGnssGeofencingCbIface->gnssGeofenceRemoveCb( |
|
geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
auto ret = mGnssGeofencingCbIface->gnssGeofencePauseCb( |
|
geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) { |
|
if (mGnssGeofencingCbIface == nullptr) { |
|
ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); |
|
return; |
|
} |
|
|
|
auto ret = mGnssGeofencingCbIface->gnssGeofenceResumeCb( |
|
geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); |
|
if (!ret.isOk()) { |
|
ALOGE("%s: Unable to invoke callback", __func__); |
|
} |
|
} |
|
|
|
pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) { |
|
return createPthread(name, start, arg, &sThreadFuncArgsList); |
|
} |
|
|
|
// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. |
|
Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) { |
|
mGnssGeofencingCbIface = callback; |
|
|
|
if (mGnssGeofencingIface == nullptr) { |
|
ALOGE("%s: GnssGeofencing interface is not available", __func__); |
|
} else { |
|
mGnssGeofencingIface->init(&sGnssGfCb); |
|
} |
|
|
|
return Void(); |
|
} |
|
|
|
Return<void> GnssGeofencing::addGeofence( |
|
int32_t geofenceId, |
|
double latitudeDegrees, |
|
double longitudeDegrees, |
|
double radiusMeters, |
|
IGnssGeofenceCallback::GeofenceTransition lastTransition, |
|
int32_t monitorTransitions, |
|
uint32_t notificationResponsivenessMs, |
|
uint32_t unknownTimerMs) { |
|
if (mGnssGeofencingIface == nullptr) { |
|
ALOGE("%s: GnssGeofencing interface is not available", __func__); |
|
return Void(); |
|
} else { |
|
mGnssGeofencingIface->add_geofence_area( |
|
geofenceId, |
|
latitudeDegrees, |
|
longitudeDegrees, |
|
radiusMeters, |
|
static_cast<int32_t>(lastTransition), |
|
monitorTransitions, |
|
notificationResponsivenessMs, |
|
unknownTimerMs); |
|
} |
|
return Void(); |
|
} |
|
|
|
Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) { |
|
if (mGnssGeofencingIface == nullptr) { |
|
ALOGE("%s: GnssGeofencing interface is not available", __func__); |
|
} else { |
|
mGnssGeofencingIface->pause_geofence(geofenceId); |
|
} |
|
return Void(); |
|
} |
|
|
|
Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) { |
|
if (mGnssGeofencingIface == nullptr) { |
|
ALOGE("%s: GnssGeofencing interface is not available", __func__); |
|
} else { |
|
mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions); |
|
} |
|
return Void(); |
|
} |
|
|
|
Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) { |
|
if (mGnssGeofencingIface == nullptr) { |
|
ALOGE("%s: GnssGeofencing interface is not available", __func__); |
|
} else { |
|
mGnssGeofencingIface->remove_geofence_area(geofenceId); |
|
} |
|
return Void(); |
|
} |
|
|
|
} // namespace implementation |
|
} // namespace V1_0 |
|
} // namespace gnss |
|
} // namespace hardware |
|
} // namespace android
|
|
|