/* * 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