android_device_xiaomi_sdm66.../android/GeofenceAPIClient.cpp
Dante Russo c85c8ff673 LocationAPI implementation
Implementation of LocationAPI into gps hal
to be a common API that is called into by platform
specific APIs.

Change-Id: Ie5a7bd217d4ae2175ad49e6aca2fb6ecd4702f3b
CRs-fixed: 1112712
2017-02-28 16:47:50 -08:00

242 lines
9.7 KiB
C++

/* Copyright (c) 2017, 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_NDDEBUG 0
#define LOG_TAG "LocSvc_GeofenceApiClient"
#include <log_util.h>
#include <loc_cfg.h>
#include "GeofenceAPIClient.h"
static void convertGpsLocation(Location& in, GpsLocation& out)
{
memset(&out, 0, sizeof(GpsLocation));
out.size = sizeof(GpsLocation);
if (in.flags & LOCATION_HAS_LAT_LONG_BIT)
out.flags |= GPS_LOCATION_HAS_LAT_LONG;
if (in.flags & LOCATION_HAS_ALTITUDE_BIT)
out.flags |= GPS_LOCATION_HAS_ALTITUDE;
if (in.flags & LOCATION_HAS_SPEED_BIT)
out.flags |= GPS_LOCATION_HAS_SPEED;
if (in.flags & LOCATION_HAS_BEARING_BIT)
out.flags |= GPS_LOCATION_HAS_BEARING;
if (in.flags & LOCATION_HAS_ACCURACY_BIT)
out.flags |= GPS_LOCATION_HAS_ACCURACY;
out.latitude = in.latitude;
out.longitude = in.longitude;
out.altitude = in.altitude;
out.speed = in.speed;
out.bearing = in.bearing;
out.accuracy = in.accuracy;
out.timestamp = (GpsUtcTime)in.timestamp;
}
GeofenceAPIClient::GeofenceAPIClient(GpsGeofenceCallbacks* cbs) :
LocationAPIClientBase(),
mGpsGeofenceCallbacks(cbs)
{
LOC_LOGD("%s]: (%p)", __func__, cbs);
LocationCallbacks locationCallbacks;
locationCallbacks.size = sizeof(LocationCallbacks);
locationCallbacks.trackingCb = nullptr;
locationCallbacks.batchingCb = nullptr;
locationCallbacks.geofenceBreachCb = nullptr;
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_transition_callback) {
locationCallbacks.geofenceBreachCb =
[this](GeofenceBreachNotification geofenceBreachNotification) {
onGeofenceBreachCb(geofenceBreachNotification);
};
}
locationCallbacks.geofenceStatusCb = nullptr;
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_status_callback) {
locationCallbacks.geofenceStatusCb =
[this](GeofenceStatusNotification geofenceStatusNotification) {
onGeofenceStatusCb(geofenceStatusNotification);
};
}
locationCallbacks.gnssLocationInfoCb = nullptr;
locationCallbacks.gnssNiCb = nullptr;
locationCallbacks.gnssSvCb = nullptr;
locationCallbacks.gnssNmeaCb = nullptr;
locationCallbacks.gnssMeasurementsCb = nullptr;
locAPISetCallbacks(locationCallbacks);
}
void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
double radius_meters, int last_transition, int monitor_transitions,
int notification_responsiveness_ms, int unknown_timer_ms)
{
LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __func__,
geofence_id, latitude, longitude, radius_meters,
last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
GeofenceOption options;
memset(&options, 0, sizeof(GeofenceOption));
options.size = sizeof(GeofenceOption);
if (monitor_transitions & GPS_GEOFENCE_ENTERED)
options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
if (monitor_transitions & GPS_GEOFENCE_EXITED)
options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT;
options.responsiveness = notification_responsiveness_ms;
GeofenceInfo data;
data.size = sizeof(GeofenceInfo);
data.latitude = latitude;
data.longitude = longitude;
data.radius = radius_meters;
locAPIAddGeofences(1, &geofence_id, &options, &data);
}
void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
{
LOC_LOGD("%s]: (%d)", __func__, geofence_id);
locAPIPauseGeofences(1, &geofence_id);
}
void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int monitor_transitions)
{
LOC_LOGD("%s]: (%d %d)", __func__, geofence_id, monitor_transitions);
GeofenceBreachTypeMask mask = 0;
if (monitor_transitions & GPS_GEOFENCE_ENTERED)
mask |= GEOFENCE_BREACH_ENTER_BIT;
if (monitor_transitions & GPS_GEOFENCE_EXITED)
mask |= GEOFENCE_BREACH_EXIT_BIT;
locAPIResumeGeofences(1, &geofence_id, &mask);
}
void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
{
LOC_LOGD("%s]: (%d)", __func__, geofence_id);
locAPIRemoveGeofences(1, &geofence_id);
}
// callbacks
void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
{
LOC_LOGD("%s]: (%zu)", __func__, geofenceBreachNotification.count);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_transition_callback) {
for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
GpsLocation location;
convertGpsLocation(geofenceBreachNotification.location, location);
uint32_t transition;
if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
transition = GPS_GEOFENCE_ENTERED;
else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
transition = GPS_GEOFENCE_EXITED;
else {
// continue with other breach if transition is
// nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
continue;
}
GpsUtcTime time = geofenceBreachNotification.timestamp;
mGpsGeofenceCallbacks->geofence_transition_callback(geofenceBreachNotification.ids[i],
&location, transition, time);
}
}
}
void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
{
LOC_LOGD("%s]: (%d)", __func__, geofenceStatusNotification.available);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_status_callback) {
int32_t status = GPS_GEOFENCE_UNAVAILABLE;
if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
status = GPS_GEOFENCE_AVAILABLE;
}
mGpsGeofenceCallbacks->geofence_status_callback(status, nullptr);
}
}
void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
{
LOC_LOGD("%s]: (%zu)", __func__, count);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_add_callback) {
for (size_t i = 0; i < count; i++) {
int32_t status = GPS_GEOFENCE_ERROR_GENERIC;
if (errors[i] == LOCATION_ERROR_SUCCESS)
status = GPS_GEOFENCE_OPERATION_SUCCESS;
mGpsGeofenceCallbacks->geofence_add_callback(ids[i], status);
}
}
}
void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
{
LOC_LOGD("%s]: (%zu)", __func__, count);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_remove_callback) {
for (size_t i = 0; i < count; i++) {
int32_t status = GPS_GEOFENCE_ERROR_GENERIC;
if (errors[i] == LOCATION_ERROR_SUCCESS)
status = GPS_GEOFENCE_OPERATION_SUCCESS;
else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
status = GPS_GEOFENCE_ERROR_ID_UNKNOWN;
mGpsGeofenceCallbacks->geofence_remove_callback(ids[i], status);
}
}
}
void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
{
LOC_LOGD("%s]: (%zu)", __func__, count);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_pause_callback) {
for (size_t i = 0; i < count; i++) {
int32_t status = GPS_GEOFENCE_ERROR_GENERIC;
if (errors[i] == LOCATION_ERROR_SUCCESS)
status = GPS_GEOFENCE_OPERATION_SUCCESS;
else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
status = GPS_GEOFENCE_ERROR_ID_UNKNOWN;
mGpsGeofenceCallbacks->geofence_pause_callback(ids[i], status);
}
}
}
void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
{
LOC_LOGD("%s]: (%zu)", __func__, count);
if (mGpsGeofenceCallbacks && mGpsGeofenceCallbacks->geofence_resume_callback) {
for (size_t i = 0; i < count; i++) {
int32_t status = GPS_GEOFENCE_ERROR_GENERIC;
if (errors[i] == LOCATION_ERROR_SUCCESS)
status = GPS_GEOFENCE_OPERATION_SUCCESS;
else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
status = GPS_GEOFENCE_ERROR_ID_UNKNOWN;
mGpsGeofenceCallbacks->geofence_resume_callback(ids[i], status);
}
}
}