From 44d5c9e2cf9f1ce0670be5bedd1e415cd5c3e739 Mon Sep 17 00:00:00 2001 From: kleidione Freitas Date: Thu, 24 Mar 2022 09:16:43 -0300 Subject: veux: Merge common tree to veux - Ref: https://github.com/xiaomi-sm6375-devs/android_device_xiaomi_sm6375-common Signed-off-by: kleidione --- gps/android/1.0/location_api/BatchingAPIClient.cpp | 197 +++++++ gps/android/1.0/location_api/BatchingAPIClient.h | 75 +++ gps/android/1.0/location_api/GeofenceAPIClient.cpp | 275 ++++++++++ gps/android/1.0/location_api/GeofenceAPIClient.h | 77 +++ gps/android/1.0/location_api/GnssAPIClient.cpp | 565 +++++++++++++++++++++ gps/android/1.0/location_api/GnssAPIClient.h | 110 ++++ gps/android/1.0/location_api/LocationUtil.cpp | 274 ++++++++++ gps/android/1.0/location_api/LocationUtil.h | 57 +++ .../1.0/location_api/MeasurementAPIClient.cpp | 276 ++++++++++ .../1.0/location_api/MeasurementAPIClient.h | 78 +++ 10 files changed, 1984 insertions(+) create mode 100644 gps/android/1.0/location_api/BatchingAPIClient.cpp create mode 100644 gps/android/1.0/location_api/BatchingAPIClient.h create mode 100644 gps/android/1.0/location_api/GeofenceAPIClient.cpp create mode 100644 gps/android/1.0/location_api/GeofenceAPIClient.h create mode 100644 gps/android/1.0/location_api/GnssAPIClient.cpp create mode 100644 gps/android/1.0/location_api/GnssAPIClient.h create mode 100644 gps/android/1.0/location_api/LocationUtil.cpp create mode 100644 gps/android/1.0/location_api/LocationUtil.h create mode 100644 gps/android/1.0/location_api/MeasurementAPIClient.cpp create mode 100644 gps/android/1.0/location_api/MeasurementAPIClient.h (limited to 'gps/android/1.0/location_api') diff --git a/gps/android/1.0/location_api/BatchingAPIClient.cpp b/gps/android/1.0/location_api/BatchingAPIClient.cpp new file mode 100644 index 0000000..94a234d --- /dev/null +++ b/gps/android/1.0/location_api/BatchingAPIClient.cpp @@ -0,0 +1,197 @@ +/* Copyright (c) 2017-2018, 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_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAPIClient" + +#include +#include +#include + +#include "LocationUtil.h" +#include "BatchingAPIClient.h" + +#include "limits.h" + + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask); + +BatchingAPIClient::BatchingAPIClient(const sp& callback) : + LocationAPIClientBase(), + mGnssBatchingCbIface(callback), + mDefaultId(UINT_MAX), + mLocationCapabilitiesMask(0) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + if (mGnssBatchingCbIface != nullptr) { + locationCallbacks.batchingCb = [this](size_t count, Location* location, + BatchingOptions batchOptions) { + onBatchingCb(count, location, batchOptions); + }; + } + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +BatchingAPIClient::~BatchingAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +int BatchingAPIClient::getBatchSize() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + return locAPIGetBatchSize(); +} + +int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; +} + +void BatchingAPIClient::onBatchingCb(size_t count, Location* location, + BatchingOptions /*batchOptions*/) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); + if (mGnssBatchingCbIface != nullptr && count > 0) { + hidl_vec locationVec; + locationVec.resize(count); + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i]); + } + auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask) +{ + memset(&out, 0, sizeof(LocationOptions)); + out.size = sizeof(LocationOptions); + out.minInterval = (uint32_t)(in.periodNanos / 1000000L); + out.minDistance = 0; + out.mode = GNSS_SUPL_MODE_STANDALONE; + if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + out.mode = GNSS_SUPL_MODE_MSA; + if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + out.mode = GNSS_SUPL_MODE_MSB; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/BatchingAPIClient.h b/gps/android/1.0/location_api/BatchingAPIClient.h new file mode 100644 index 0000000..c3b0a7b --- /dev/null +++ b/gps/android/1.0/location_api/BatchingAPIClient.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#ifndef BATCHING_API_CLINET_H +#define BATCHING_API_CLINET_H + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp& callback); + int getBatchSize(); + int startSession(const V1_0::IGnssBatching::Options& options); + int updateSessionOptions(const V1_0::IGnssBatching::Options& options); + int stopSession(); + void getBatchedLocation(int last_n_locations); + void flushBatchedLocations(); + + inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; } + + // callbacks + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final; + +private: + ~BatchingAPIClient(); + + sp mGnssBatchingCbIface; + uint32_t mDefaultId; + LocationCapabilitiesMask mLocationCapabilitiesMask; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // BATCHING_API_CLINET_H diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.cpp b/gps/android/1.0/location_api/GeofenceAPIClient.cpp new file mode 100644 index 0000000..774a049 --- /dev/null +++ b/gps/android/1.0/location_api/GeofenceAPIClient.cpp @@ -0,0 +1,275 @@ +/* Copyright (c) 2017-2018, 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_NDEBUG 0 +#define LOG_TAG "LocSvc_GeofenceApiClient" + +#include +#include + +#include "LocationUtil.h" +#include "GeofenceAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +GeofenceAPIClient::GeofenceAPIClient(const sp& callback) : + LocationAPIClientBase(), + mGnssGeofencingCbIface(callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + + locationCallbacks.geofenceBreachCb = nullptr; + if (mGnssGeofencingCbIface != nullptr) { + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + onGeofenceBreachCb(geofenceBreachNotification); + }; + + 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, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) +{ + LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, + 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 & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::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; + + LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); + if (LOCATION_ERROR_SUCCESS != err) { + onAddGeofencesCb(1, &err, &geofence_id); + } +} + +void GeofenceAPIClient::geofencePause(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIPauseGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); + GeofenceBreachTypeMask mask = 0; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + mask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + mask |= GEOFENCE_BREACH_EXIT_BIT; + locAPIResumeGeofences(1, &geofence_id, &mask); +} + +void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIRemoveGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceRemoveAll() +{ + LOC_LOGD("%s]", __FUNCTION__); + // TODO locAPIRemoveAllGeofences(); +} + +// callbacks +void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < geofenceBreachNotification.count; i++) { + GnssLocation gnssLocation; + convertGnssLocation(geofenceBreachNotification.location, gnssLocation); + + IGnssGeofenceCallback::GeofenceTransition transition; + if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) + transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; + else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) + transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; + else { + // continue with other breach if transition is + // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED + continue; + } + + auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( + geofenceBreachNotification.ids[i], gnssLocation, transition, + static_cast(geofenceBreachNotification.timestamp)); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); + if (mGnssGeofencingCbIface != nullptr) { + IGnssGeofenceCallback::GeofenceAvailability status = + IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; + if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { + status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; + } + GnssLocation gnssLocation; + memset(&gnssLocation, 0, sizeof(GnssLocation)); + auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_EXISTS) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; + auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.h b/gps/android/1.0/location_api/GeofenceAPIClient.h new file mode 100644 index 0000000..b6a009b --- /dev/null +++ b/gps/android/1.0/location_api/GeofenceAPIClient.h @@ -0,0 +1,77 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#ifndef GEOFENCE_API_CLINET_H +#define GEOFENCE_API_CLINET_H + + +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp& callback); + + void geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms); + void geofencePause(uint32_t geofence_id); + void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions); + void geofenceRemove(uint32_t geofence_id); + void geofenceRemoveAll(); + + // callbacks + void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final; + void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final; + void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + +private: + virtual ~GeofenceAPIClient() = default; + + sp mGnssGeofencingCbIface; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GEOFENCE_API_CLINET_H diff --git a/gps/android/1.0/location_api/GnssAPIClient.cpp b/gps/android/1.0/location_api/GnssAPIClient.cpp new file mode 100644 index 0000000..4247258 --- /dev/null +++ b/gps/android/1.0/location_api/GnssAPIClient.cpp @@ -0,0 +1,565 @@ +/* Copyright (c) 2017-2020, 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_NDEBUG 0 +#define LOG_TAG "LocSvc_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include +#include +#include + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnss; +using ::android::hardware::gnss::V1_0::IGnssCallback; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); + +GnssAPIClient::GnssAPIClient(const sp& gpsCb, + const sp& niCb) : + LocationAPIClientBase(), + mGnssCbIface(nullptr), + mGnssNiCbIface(nullptr), + mControlClient(new LocationAPIControlClient()), + mLocationCapabilitiesMask(0), + mLocationCapabilitiesCached(false) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + // set default LocationOptions. + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = 1000; + mTrackingOptions.minDistance = 0; + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + + gnssUpdateCallbacks(gpsCb, niCb); +} + +GnssAPIClient::~GnssAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient) { + delete mControlClient; + mControlClient = nullptr; + } +} + +// for GpsInterface +void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + mMutex.lock(); + mGnssCbIface = gpsCb; + mGnssNiCbIface = niCb; + mMutex.unlock(); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.trackingCb = [this](Location location) { + onTrackingCb(location); + }; + } + + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + + locationCallbacks.gnssNiCb = nullptr; + loc_core::ContextBase* context = + loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName); + if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { + LOC_LOGD("Registering NI CB"); + locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { + onGnssNiCb(id, gnssNiNotification); + }; + } + + locationCallbacks.gnssSvCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) { + onGnssSvCb(gnssSvNotification); + }; + } + + locationCallbacks.gnssNmeaCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) { + onGnssNmeaCb(gnssNmeaNotification); + }; + } + + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +bool GnssAPIClient::gnssStart() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStartTracking(mTrackingOptions); + return retVal; +} + +bool GnssAPIClient::gnssStop() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStopTracking(); + return retVal; +} + +bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, + IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__, + (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, + preferredTimeMs, (int)powerMode, timeBetweenMeasurement); + bool retVal = true; + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = minIntervalMs; + if (IGnss::GnssPositionMode::MS_ASSISTED == mode || + IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) { + // We set a very large interval to simulate SINGLE mode. Once we report a fix, + // the caller should take the responsibility to stop the session. + // For MSA, we always treat it as SINGLE mode. + mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC; + } + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; + data.posEngineMask = STANDARD_POSITIONING_ENGINE; + + if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) + data.deleteAll = true; + else { + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) + data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) + data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) + data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) + data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) + data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) + data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) + data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) + data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) + data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) + data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) + data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) + data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; + } + mControlClient->locAPIGnssDeleteAidingData(data); +} + +void GnssAPIClient::gnssEnable(LocationTechnologyType techType) +{ + LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIEnable(techType); +} + +void GnssAPIClient::gnssDisable() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIDisable(); +} + +void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIGnssUpdateConfig(gnssConfig); +} + +void GnssAPIClient::requestCapabilities() { + // only send capablities if it's already cached, otherwise the first time LocationAPI + // is initialized, capabilities will be sent by LocationAPI + if (mLocationCapabilitiesCached) { + onCapabilitiesCb(mLocationCapabilitiesMask); + } +} + +// callbacks +void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; + mLocationCapabilitiesCached = true; + + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + uint32_t data = 0; + if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT)) + data |= IGnssCallback::Capabilities::SCHEDULING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT) + data |= IGnssCallback::Capabilities::GEOFENCING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) + data |= IGnssCallback::Capabilities::MEASUREMENTS; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + data |= IGnssCallback::Capabilities::MSB; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + data |= IGnssCallback::Capabilities::MSA; + auto r = gnssCbIface->gnssSetCapabilitesCb(data); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s", + __func__, r.description().c_str()); + } + } + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 }; + + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw++; // 2016 + if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw++; // 2017 + if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw++; // 2018 + } + } + } + LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); + auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onTrackingCb(Location location) +{ + LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + GnssLocation gnssLocation; + convertGnssLocation(location, gnssLocation); + auto r = gnssCbIface->gnssLocationCb(gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) +{ + LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); + mMutex.lock(); + auto gnssNiCbIface(mGnssNiCbIface); + mMutex.unlock(); + + if (gnssNiCbIface == nullptr) { + LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); + return; + } + + IGnssNiCallback::GnssNiNotification notificationGnss = {}; + + notificationGnss.notificationId = id; + + if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; + else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; + + if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; + + notificationGnss.timeoutSec = gnssNiNotification.timeout; + + if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || + gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; + + notificationGnss.requestorId = gnssNiNotification.requestor; + + notificationGnss.notificationMessage = gnssNiNotification.message; + + if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + gnssNiCbIface->niNotifyCb(notificationGnss); +} + +void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSvStatus svStatus; + convertGnssSvStatus(gnssSvNotification, svStatus); + auto r = gnssCbIface->gnssSvStatusCb(svStatus); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) +{ + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + const std::string s(gnssNmeaNotification.nmea); + std::stringstream ss(s); + std::string each; + while(std::getline(ss, each, '\n')) { + each += '\n'; + android::hardware::hidl_string nmeaString; + nmeaString.setToExternal(each.c_str(), each.length()); + auto r = gnssCbIface->gnssNmeaCb( + static_cast(gnssNmeaNotification.timestamp), nmeaString); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, + gnssNmeaNotification.nmea, gnssNmeaNotification.length, + r.description().c_str()); + } + } + } +} + +void GnssAPIClient::onStartTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onStopTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) +{ + memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); + out.numSvs = in.count; + if (out.numSvs > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; + convertGnssSvid(in.gnssSvs[i], info.svid); + convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); + info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; + info.elevationDegrees = in.gnssSvs[i].elevation; + info.azimuthDegrees = in.gnssSvs[i].azimuth; + info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; + info.svFlag = static_cast(IGnssCallback::GnssSvFlags::NONE); + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/GnssAPIClient.h b/gps/android/1.0/location_api/GnssAPIClient.h new file mode 100644 index 0000000..427b0db --- /dev/null +++ b/gps/android/1.0/location_api/GnssAPIClient.h @@ -0,0 +1,110 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#ifndef GNSS_API_CLINET_H +#define GNSS_API_CLINET_H + + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp& gpsCb, + const sp& niCb); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb); + bool gnssStart(); + bool gnssStop(); + bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = 0); + + // for GpsNiInterface + void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse); + + // these apis using LocationAPIControlClient + void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags); + void gnssEnable(LocationTechnologyType techType); + void gnssDisable(); + void gnssConfigurationUpdate(const GnssConfig& gnssConfig); + + inline LocationCapabilitiesMask gnssGetCapabilities() const { + return mLocationCapabilitiesMask; + } + void requestCapabilities(); + + // callbacks we are interested in + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onTrackingCb(Location location) final; + void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final; + void onGnssSvCb(GnssSvNotification gnssSvNotification) final; + void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final; + + void onStartTrackingCb(LocationError error) final; + void onStopTrackingCb(LocationError error) final; + +private: + virtual ~GnssAPIClient(); + + sp mGnssCbIface; + sp mGnssNiCbIface; + std::mutex mMutex; + LocationAPIControlClient* mControlClient; + LocationCapabilitiesMask mLocationCapabilitiesMask; + bool mLocationCapabilitiesCached; + TrackingOptions mTrackingOptions; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GNSS_API_CLINET_H diff --git a/gps/android/1.0/location_api/LocationUtil.cpp b/gps/android/1.0/location_api/LocationUtil.cpp new file mode 100644 index 0000000..870a8aa --- /dev/null +++ b/gps/android/1.0/location_api/LocationUtil.cpp @@ -0,0 +1,274 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::V1_0::GnssConstellationType; +using ::android::hardware::gnss::V1_0::GnssLocationFlags; + +void convertGnssLocation(Location& in, GnssLocation& out) +{ + memset(&out, 0, sizeof(GnssLocation)); + if (in.flags & LOCATION_HAS_LAT_LONG_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG; + out.latitudeDegrees = in.latitude; + out.longitudeDegrees = in.longitude; + } + if (in.flags & LOCATION_HAS_ALTITUDE_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE; + out.altitudeMeters = in.altitude; + } + if (in.flags & LOCATION_HAS_SPEED_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED; + out.speedMetersPerSec = in.speed; + } + if (in.flags & LOCATION_HAS_BEARING_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING; + out.bearingDegrees = in.bearing; + } + if (in.flags & LOCATION_HAS_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY; + out.horizontalAccuracyMeters = in.accuracy; + } + if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY; + out.verticalAccuracyMeters = in.verticalAccuracy; + } + if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY; + out.speedAccuracyMetersPerSecond = in.speedAccuracy; + } + if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY; + out.bearingAccuracyDegrees = in.bearingAccuracy; + } + + out.timestamp = static_cast(in.timestamp); +} + +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) { + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) { + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + out.altitude = in.altitudeMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) { + out.flags |= LOCATION_HAS_SPEED_BIT; + out.speed = in.speedMetersPerSec; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + out.flags |= LOCATION_HAS_BEARING_BIT; + out.bearing = in.bearingDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + out.flags |= LOCATION_HAS_ACCURACY_BIT; + out.accuracy = in.horizontalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + out.verticalAccuracy = in.verticalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.bearingAccuracy = in.bearingAccuracyDegrees; + } + + out.timestamp = static_cast(in.timestamp); +} + +void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) +{ + switch(in) { + case GNSS_SV_TYPE_GPS: + out = GnssConstellationType::GPS; + break; + case GNSS_SV_TYPE_SBAS: + out = GnssConstellationType::SBAS; + break; + case GNSS_SV_TYPE_GLONASS: + out = GnssConstellationType::GLONASS; + break; + case GNSS_SV_TYPE_QZSS: + out = GnssConstellationType::QZSS; + break; + case GNSS_SV_TYPE_BEIDOU: + out = GnssConstellationType::BEIDOU; + break; + case GNSS_SV_TYPE_GALILEO: + out = GnssConstellationType::GALILEO; + break; + case GNSS_SV_TYPE_UNKNOWN: + default: + out = GnssConstellationType::UNKNOWN; + break; + } +} + +void convertGnssSvid(GnssSv& in, int16_t& out) +{ + switch(in.type){ + case GNSS_SV_TYPE_GPS: + out = in.svId; + break; + case GNSS_SV_TYPE_SBAS: + out = in.svId; + break; + case GNSS_SV_TYPE_GLONASS: + if (!isGloSlotUnknown(in.svId)) { // OSN is known + out = in.svId - GLO_SV_PRN_MIN + 1; + } else { // OSN is not known, report FCN + out = in.gloFrequency + 92; + } + break; + case GNSS_SV_TYPE_QZSS: + out = in.svId; + break; + case GNSS_SV_TYPE_BEIDOU: + out = in.svId - BDS_SV_PRN_MIN + 1; + break; + case GNSS_SV_TYPE_GALILEO: + out = in.svId - GAL_SV_PRN_MIN + 1; + break; + case GNSS_SV_TYPE_NAVIC: + out = in.svId - NAVIC_SV_PRN_MIN + 1; + break; + default: + out = in.svId; + break; + } +} + +void convertGnssSvid(GnssMeasurementsData& in, int16_t& out) +{ + switch (in.svType) { + case GNSS_SV_TYPE_GPS: + out = in.svId; + break; + case GNSS_SV_TYPE_SBAS: + out = in.svId; + break; + case GNSS_SV_TYPE_GLONASS: + if (!isGloSlotUnknown(in.svId)) { // OSN is known + out = in.svId - GLO_SV_PRN_MIN + 1; + } else { // OSN is not known, report FCN + out = in.gloFrequency + 92; + } + break; + case GNSS_SV_TYPE_QZSS: + out = in.svId; + break; + case GNSS_SV_TYPE_BEIDOU: + out = in.svId - BDS_SV_PRN_MIN + 1; + break; + case GNSS_SV_TYPE_GALILEO: + out = in.svId - GAL_SV_PRN_MIN + 1; + break; + case GNSS_SV_TYPE_NAVIC: + out = in.svId - NAVIC_SV_PRN_MIN + 1; + break; + default: + out = in.svId; + break; + } +} + +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out) +{ + switch(in) { + case GNSS_EPH_TYPE_EPHEMERIS: + out = GnssDebug::SatelliteEphemerisType::EPHEMERIS; + break; + case GNSS_EPH_TYPE_ALMANAC: + out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY; + break; + case GNSS_EPH_TYPE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE; + break; + } +} + +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out) +{ + switch(in) { + case GNSS_EPH_SOURCE_DEMODULATED: + out = GnssDebug::SatelliteEphemerisSource::DEMODULATED; + break; + case GNSS_EPH_SOURCE_SUPL_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED; + break; + case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED; + break; + case GNSS_EPH_SOURCE_LOCAL: + case GNSS_EPH_SOURCE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisSource::OTHER; + break; + } +} + +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out) +{ + switch(in) { + case GNSS_EPH_HEALTH_GOOD: + out = GnssDebug::SatelliteEphemerisHealth::GOOD; + break; + case GNSS_EPH_HEALTH_BAD: + out = GnssDebug::SatelliteEphemerisHealth::BAD; + break; + case GNSS_EPH_HEALTH_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN; + break; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/LocationUtil.h b/gps/android/1.0/location_api/LocationUtil.h new file mode 100644 index 0000000..f6760e5 --- /dev/null +++ b/gps/android/1.0/location_api/LocationUtil.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#ifndef LOCATION_UTIL_H +#define LOCATION_UTIL_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void convertGnssLocation(Location& in, V1_0::GnssLocation& out); +void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); +void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); +void convertGnssSvid(GnssSv& in, int16_t& out); +void convertGnssSvid(GnssMeasurementsData& in, int16_t& out); +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // LOCATION_UTIL_H diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.cpp b/gps/android/1.0/location_api/MeasurementAPIClient.cpp new file mode 100644 index 0000000..9b23308 --- /dev/null +++ b/gps/android/1.0/location_api/MeasurementAPIClient.cpp @@ -0,0 +1,276 @@ +/* Copyright (c) 2017-2018, 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_NDEBUG 0 +#define LOG_TAG "LocSvc_MeasurementAPIClient" + +#include +#include + +#include "LocationUtil.h" +#include "MeasurementAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssMeasurement; +using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback; + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out); +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out); +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out); + +MeasurementAPIClient::MeasurementAPIClient() : + mGnssMeasurementCbIface(nullptr), + mTracking(false) +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +MeasurementAPIClient::~MeasurementAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +// for GpsInterface +Return +MeasurementAPIClient::measurementSetCallback(const sp& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return +MeasurementAPIClient::startTracking() +{ + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + + locationCallbacks.gnssMeasurementsCb = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + locationCallbacks.gnssMeasurementsCb = + [this](GnssMeasurementsNotification gnssMeasurementsNotification) { + onGnssMeasurementsCb(gnssMeasurementsNotification); + }; + } + + locAPISetCallbacks(locationCallbacks); + + TrackingOptions options = {}; + memset(&options, 0, sizeof(TrackingOptions)); + options.size = sizeof(TrackingOptions); + options.minInterval = 1000; + options.mode = GNSS_SUPL_MODE_STANDALONE; + + mTracking = true; + LOC_LOGD("%s]: start tracking session", __FUNCTION__); + locAPIStartTracking(options); + return IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +// for GpsMeasurementInterface +void MeasurementAPIClient::measurementClose() { + LOC_LOGD("%s]: ()", __FUNCTION__); + mTracking = false; + locAPIStopTracking(); +} + +// callbacks +void MeasurementAPIClient::onGnssMeasurementsCb( + GnssMeasurementsNotification gnssMeasurementsNotification) +{ + LOC_LOGD("%s]: (count: %zu active: %d)", + __FUNCTION__, gnssMeasurementsNotification.count, mTracking); + if (mTracking) { + mMutex.lock(); + sp gnssMeasurementCbIface = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + gnssMeasurementCbIface = mGnssMeasurementCbIface; + } + mMutex.unlock(); + + if (gnssMeasurementCbIface != nullptr) { + V1_0::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from GnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement)); + if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL; + convertGnssSvid(in, out.svid); + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.h b/gps/android/1.0/location_api/MeasurementAPIClient.h new file mode 100644 index 0000000..225deac --- /dev/null +++ b/gps/android/1.0/location_api/MeasurementAPIClient.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2017-2018, 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. + * + */ + +#ifndef MEASUREMENT_API_CLINET_H +#define MEASUREMENT_API_CLINET_H + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return measurementSetCallback( + const sp& callback); + void measurementClose(); + Return startTracking(); + + // callbacks we are interested in + void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final; + +private: + virtual ~MeasurementAPIClient(); + + std::mutex mMutex; + sp mGnssMeasurementCbIface; + + bool mTracking; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // MEASUREMENT_API_CLINET_H -- cgit v1.2.3