aboutsummaryrefslogtreecommitdiff
path: root/gps/android/2.1/location_api
diff options
context:
space:
mode:
authorkleidione Freitas <kleidione@gmail.com>2022-03-24 09:16:43 -0300
committerkleidione <kleidione@gmail.com>2022-11-09 17:29:16 -0300
commit44d5c9e2cf9f1ce0670be5bedd1e415cd5c3e739 (patch)
tree4516fedba0c65fda9e795d8737d08a7746d41e40 /gps/android/2.1/location_api
parent15eeafbf239f393fcb6ed1a719398e5b7bbd6a19 (diff)
veux: Merge common tree to veux
- Ref: https://github.com/xiaomi-sm6375-devs/android_device_xiaomi_sm6375-common Signed-off-by: kleidione <kleidione@gmail.com>
Diffstat (limited to 'gps/android/2.1/location_api')
-rw-r--r--gps/android/2.1/location_api/BatchingAPIClient.cpp251
-rwxr-xr-xgps/android/2.1/location_api/BatchingAPIClient.h82
-rwxr-xr-xgps/android/2.1/location_api/GeofenceAPIClient.cpp275
-rwxr-xr-xgps/android/2.1/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/2.1/location_api/GnssAPIClient.cpp864
-rwxr-xr-xgps/android/2.1/location_api/GnssAPIClient.h118
-rw-r--r--gps/android/2.1/location_api/LocationUtil.cpp405
-rw-r--r--gps/android/2.1/location_api/LocationUtil.h68
-rw-r--r--gps/android/2.1/location_api/MeasurementAPIClient.cpp642
-rw-r--r--gps/android/2.1/location_api/MeasurementAPIClient.h96
10 files changed, 2878 insertions, 0 deletions
diff --git a/gps/android/2.1/location_api/BatchingAPIClient.cpp b/gps/android/2.1/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..00d2ed9
--- /dev/null
+++ b/gps/android/2.1/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,251 @@
+/* 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_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks(callback);
+}
+
+BatchingAPIClient::BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks_2_0(callback);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+void BatchingAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = 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);
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(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<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(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*/)
+{
+ mMutex.lock();
+ auto gnssBatchingCbIface(mGnssBatchingCbIface);
+ auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0);
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (gnssBatchingCbIface_2_0 != nullptr && count > 0) {
+ hidl_vec<V2_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<V1_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 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 V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/BatchingAPIClient.h b/gps/android/2.1/location_api/BatchingAPIClient.h
new file mode 100755
index 0000000..08d7d23
--- /dev/null
+++ b/gps/android/2.1/location_api/BatchingAPIClient.h
@@ -0,0 +1,82 @@
+/* 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.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+ BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& 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();
+
+ void setCallbacks();
+ std::mutex mMutex;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/2.1/location_api/GeofenceAPIClient.cpp b/gps/android/2.1/location_api/GeofenceAPIClient.cpp
new file mode 100755
index 0000000..6e63465
--- /dev/null
+++ b/gps/android/2.1/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* 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_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& 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]: (%d)", __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<V1_0::GnssUtcTime>(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 V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/GeofenceAPIClient.h b/gps/android/2.1/location_api/GeofenceAPIClient.h
new file mode 100755
index 0000000..9ed289f
--- /dev/null
+++ b/gps/android/2.1/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* 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.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+ GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& 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<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/2.1/location_api/GnssAPIClient.cpp b/gps/android/2.1/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..07f617d
--- /dev/null
+++ b/gps/android/2.1/location_api/GnssAPIClient.cpp
@@ -0,0 +1,864 @@
+/* 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 <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnss;
+using ::android::hardware::gnss::V2_1::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out);
+
+GnssAPIClient::GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks_2_0(gpsCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_1(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks_2_1(gpsCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+void GnssAPIClient::initLocationOptions()
+{
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+}
+
+void GnssAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ if (mGnssNiCbIface != nullptr) {
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (!context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) {
+ onGnssNiCb(id, gnssNiNotify);
+ };
+ }
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ mMutex.lock();
+ mGnssCbIface_2_0 = gpsCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ mMutex.lock();
+ mGnssCbIface_2_1 = gpsCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface_2_1 != nullptr) {
+ setCallbacks();
+ }
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = true;
+ mMutex.unlock();
+
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = false;
+ mMutex.unlock();
+
+ 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<int>(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 |
+ GNSS_AIDING_DATA_SV_TYPE_NAVIC_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);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_1 != nullptr ||gnssCbIface_2_0 != nullptr || gnssCbIface != nullptr) {
+
+ uint32_t antennaInfoVectorSize = 0;
+ uint32_t data = 0;
+ loc_param_s_type ant_info_vector_table[] =
+ {
+ { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
+ };
+ UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
+
+ if (0 != antennaInfoVectorSize) {
+ data |= V2_1::IGnssCallback::Capabilities::ANTENNA_INFO;
+ }
+
+ 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 |= V1_0::IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= V1_0::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;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT)
+ data |= IGnssCallback::Capabilities::LOW_POWER_MODE;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT)
+ data |= IGnssCallback::Capabilities::SATELLITE_BLACKLIST;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT)
+ data |= V2_0::IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS;
+
+ 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
+ if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
+ gnssInfo.yearOfHw++; // 2019
+ if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT) {
+ gnssInfo.yearOfHw++; // 2020
+ }
+ }
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssSetCapabilitiesCb_2_1(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_1 description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssSetCapabilitiesCb_2_0(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ 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)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ bool isTracking = mTracking;
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (flags: %02x isTracking: %d)", __FUNCTION__, location.flags, isTracking);
+
+ if (!isTracking) {
+ return;
+ }
+
+ if (gnssCbIface_2_1 != nullptr) {
+ V2_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface_2_1->gnssLocationCb_2_0(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ V2_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface_2_0->gnssLocationCb_2_0(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::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());
+ }
+ } else {
+ LOC_LOGW("%s] No GNSS Interface ready for gnssLocationCb ", __FUNCTION__);
+ }
+
+}
+
+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: %u)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_1 != nullptr) {
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo> svInfoList;
+ convertGnssSvStatus(gnssSvNotification, svInfoList);
+ auto r = gnssCbIface_2_1->gnssSvStatusCb_2_1(svInfoList);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb_2_1 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo> svInfoList;
+ convertGnssSvStatus(gnssSvNotification, svInfoList);
+ auto r = gnssCbIface_2_0->gnssSvStatusCb_2_0(svInfoList);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::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);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr || gnssCbIface_2_0 != nullptr| gnssCbIface_2_1 != 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());
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssCbIface_2_1 nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssCbIface_2_0 nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u 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);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (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);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+
+ } else if (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, V1_0::IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<uint32_t>(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<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.numSvs; i++) {
+ convertGnssSvid(in.gnssSvs[i], out.gnssSvList[i].svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, out.gnssSvList[i].constellation);
+ out.gnssSvList[i].cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out.gnssSvList[i].elevationDegrees = in.gnssSvs[i].elevation;
+ out.gnssSvList[i].azimuthDegrees = in.gnssSvs[i].azimuth;
+ out.gnssSvList[i].carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out.gnssSvList[i].svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out)
+{
+ out.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssSvid(in.gnssSvs[i], out[i].v1_0.svid);
+ out[i].v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out[i].v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+ out[i].v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+ out[i].v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out[i].v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+ convertGnssConstellationType(in.gnssSvs[i].type, out[i].constellation);
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out)
+{
+ out.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssSvid(in.gnssSvs[i], out[i].v2_0.v1_0.svid);
+ out[i].v2_0.v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out[i].v2_0.v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+ out[i].v2_0.v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+ out[i].v2_0.v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out[i].v2_0.v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+ convertGnssConstellationType(in.gnssSvs[i].type, out[i].v2_0.constellation);
+ out[i].basebandCN0DbHz = in.gnssSvs[i].basebandCarrierToNoiseDbHz;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/GnssAPIClient.h b/gps/android/2.1/location_api/GnssAPIClient.h
new file mode 100755
index 0000000..c4dbe9a
--- /dev/null
+++ b/gps/android/2.1/location_api/GnssAPIClient.h
@@ -0,0 +1,118 @@
+/* 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.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/2.1/IGnssCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+ GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb);
+ GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb);
+ GnssAPIClient(const GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb);
+ void gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb);
+ 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();
+ void setCallbacks();
+ void initLocationOptions();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+ bool mTracking;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0;
+ sp<V2_1::IGnssCallback> mGnssCbIface_2_1;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/2.1/location_api/LocationUtil.cpp b/gps/android/2.1/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..5154e70
--- /dev/null
+++ b/gps/android/2.1/location_api/LocationUtil.cpp
@@ -0,0 +1,405 @@
+/* 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.
+ *
+ */
+
+#include <LocationUtil.h>
+#include <log_util.h>
+#include <inttypes.h>
+#include <loc_misc_utils.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssLocation;
+using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+using ::android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V1_0::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<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V2_0::GnssLocation));
+ convertGnssLocation(in, out.v1_0);
+
+ if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ out.elapsedRealtime.timestampNs = in.elapsedRealTime;
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+ LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
+ " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
+ " out.elapsedRealtime.flags=0x%X",
+ out.elapsedRealtime.timestampNs,
+ out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
+ }
+}
+
+void convertGnssLocation(const V1_0::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<uint64_t>(in.timestamp);
+}
+
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ convertGnssLocation(in.v1_0, out);
+}
+
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V1_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V1_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V1_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V1_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V1_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V1_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V1_0::GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V2_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V2_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V2_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V2_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V2_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V2_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = V2_0::GnssConstellationType::IRNSS;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V2_0::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;
+ }
+}
+
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out)
+{
+ out.flags = GNSS_MEAS_CORR_UNKNOWN_BIT;
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT;
+ }
+ switch (in.constellation) {
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GPS):
+ out.svType = GNSS_SV_TYPE_GPS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::SBAS):
+ out.svType = GNSS_SV_TYPE_SBAS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GLONASS):
+ out.svType = GNSS_SV_TYPE_GLONASS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::QZSS):
+ out.svType = GNSS_SV_TYPE_QZSS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::BEIDOU):
+ out.svType = GNSS_SV_TYPE_BEIDOU;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GALILEO):
+ out.svType = GNSS_SV_TYPE_GALILEO;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::UNKNOWN):
+ default:
+ out.svType = GNSS_SV_TYPE_UNKNOWN;
+ break;
+ }
+ out.svId = in.svid;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.probSatIsLos = in.probSatIsLos;
+ out.excessPathLengthMeters = in.excessPathLengthMeters;
+ out.excessPathLengthUncertaintyMeters = in.excessPathLengthUncertaintyMeters;
+
+ out.reflectingPlane.latitudeDegrees = in.reflectingPlane.latitudeDegrees;
+ out.reflectingPlane.longitudeDegrees = in.reflectingPlane.longitudeDegrees;
+ out.reflectingPlane.altitudeMeters = in.reflectingPlane.altitudeMeters;
+ out.reflectingPlane.azimuthDegrees = in.reflectingPlane.azimuthDegrees;
+}
+
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+ GnssMeasurementCorrections& out)
+{
+ memset(&out, 0, sizeof(GnssMeasurementCorrections));
+ out.latitudeDegrees = in.latitudeDegrees;
+ out.longitudeDegrees = in.longitudeDegrees;
+ out.altitudeMeters = in.altitudeMeters;
+ out.horizontalPositionUncertaintyMeters = in.horizontalPositionUncertaintyMeters;
+ out.verticalPositionUncertaintyMeters = in.verticalPositionUncertaintyMeters;
+ out.toaGpsNanosecondsOfWeek = in.toaGpsNanosecondsOfWeek;
+
+ for (int i = 0; i < in.satCorrections.size(); i++) {
+ GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+ convertSingleSatCorrections(in.satCorrections[i], gnssSingleSatCorrection);
+ out.satCorrections.push_back(gnssSingleSatCorrection);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/LocationUtil.h b/gps/android/2.1/location_api/LocationUtil.h
new file mode 100644
index 0000000..2d95a2d
--- /dev/null
+++ b/gps/android/2.1/location_api/LocationUtil.h
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/2.0/types.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using ::android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssConstellationType(GnssSvType& in, V2_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);
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out);
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+ GnssMeasurementCorrections& out);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/2.1/location_api/MeasurementAPIClient.cpp b/gps/android/2.1/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..0028074
--- /dev/null
+++ b/gps/android/2.1/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,642 @@
+/* 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_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+#include <inttypes.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+ V2_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssClock_2_1(GnssMeasurementsClock& in,
+ V2_1::IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+ char* inOtherCodeTypeName,
+ ::android::hardware::hidl_string& out);
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out);
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mGnssMeasurementCbIface_1_1(nullptr),
+ mGnssMeasurementCbIface_2_0(nullptr),
+ mGnssMeasurementCbIface_2_1(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+void MeasurementAPIClient::clearInterfaces()
+{
+ mGnssMeasurementCbIface = nullptr;
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ mGnssMeasurementCbIface_2_1 = nullptr;
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_1_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus> MeasurementAPIClient::measurementSetCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) {
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_2_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking(
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ 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_2_1 != nullptr ||
+ mGnssMeasurementCbIface_2_0 != nullptr ||
+ mGnssMeasurementCbIface_1_1 != nullptr ||
+ 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;
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ options.powerMode = powerMode;
+ options.tbm = timeBetweenMeasurement;
+ }
+
+ 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: %u active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssMeasurementCallback> gnssMeasurementCbIface_2_1 = nullptr;
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ gnssMeasurementCbIface_2_1 = mGnssMeasurementCbIface_2_1;
+ } else if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0;
+ } else if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+ } else if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface_2_1 != nullptr) {
+ V2_1::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_2_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_2_1->gnssMeasurementCb_2_1(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface_2_0 != nullptr) {
+ V2_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_2_0(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface_1_1 != nullptr) {
+ V1_1::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else 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(out));
+ 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<uint8_t>(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<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+ out.snrDb = in.signalToNoiseRatioDb;
+ out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(out));
+ 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 convertGnssClock_2_1(GnssMeasurementsClock& in,
+ V2_1::IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(out));
+ convertGnssClock(in, out.v1_0);
+ convertGnssConstellationType(in.referenceSignalTypeForIsb.svType,
+ out.referenceSignalTypeForIsb.constellation);
+ out.referenceSignalTypeForIsb.carrierFrequencyHz =
+ in.referenceSignalTypeForIsb.carrierFrequencyHz;
+ convertGnssMeasurementsCodeType(in.referenceSignalTypeForIsb.codeType,
+ in.referenceSignalTypeForIsb.otherCodeTypeName,
+ out.referenceSignalTypeForIsb.codeType);
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<uint32_t>(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<uint32_t>(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);
+}
+
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].accumulatedDeltaRangeState);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
+ convertGnssConstellationType(in.measurements[i].svType, out.measurements[i].constellation);
+ convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+ in.measurements[i].otherCodeTypeName,
+ out.measurements[i].codeType);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].v1_1.accumulatedDeltaRangeState);
+ convertGnssMeasurementsState(in.measurements[i].stateMask, out.measurements[i].state);
+ }
+ convertGnssClock(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+ char* inOtherCodeTypeName, ::android::hardware::hidl_string& out)
+{
+ memset(&out, 0, sizeof(out));
+ switch(inCodeType) {
+ case GNSS_MEASUREMENTS_CODE_TYPE_A:
+ out = "A";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_B:
+ out = "B";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_C:
+ out = "C";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_I:
+ out = "I";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_L:
+ out = "L";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_M:
+ out = "M";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_P:
+ out = "P";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Q:
+ out = "Q";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_S:
+ out = "S";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_W:
+ out = "W";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_X:
+ out = "X";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Y:
+ out = "Y";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Z:
+ out = "Z";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_N:
+ out = "N";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_OTHER:
+ default:
+ out = inOtherCodeTypeName;
+ break;
+ }
+}
+
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out |= IGnssMeasurementCallback::
+ GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+}
+
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+ if (in & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
+}
+
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+ V2_1::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ out.measurements[i].flags = 0;
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v2_0.v1_1.v1_0);
+ convertGnssConstellationType(in.measurements[i].svType,
+ out.measurements[i].v2_0.constellation);
+ convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+ in.measurements[i].otherCodeTypeName,
+ out.measurements[i].v2_0.codeType);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].v2_0.v1_1.accumulatedDeltaRangeState);
+ convertGnssMeasurementsState(in.measurements[i].stateMask,
+ out.measurements[i].v2_0.state);
+ out.measurements[i].basebandCN0DbHz = in.measurements[i].basebandCarrierToNoiseDbHz;
+
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT) {
+ out.measurements[i].fullInterSignalBiasNs = in.measurements[i].fullInterSignalBiasNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_FULL_ISB;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT) {
+ out.measurements[i].fullInterSignalBiasUncertaintyNs =
+ in.measurements[i].fullInterSignalBiasUncertaintyNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT) {
+ out.measurements[i].satelliteInterSignalBiasNs =
+ in.measurements[i].satelliteInterSignalBiasNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SATELLITE_ISB;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT) {
+ out.measurements[i].satelliteInterSignalBiasUncertaintyNs =
+ in.measurements[i].satelliteInterSignalBiasUncertaintyNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY;
+ }
+ }
+ convertGnssClock_2_1(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+ if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+ LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
+ " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
+ elapsedRealtime.timestampNs,
+ elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/MeasurementAPIClient.h b/gps/android/2.1/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..3e8805b
--- /dev/null
+++ b/gps/android/2.1/location_api/MeasurementAPIClient.h
@@ -0,0 +1,96 @@
+/* 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.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <android/hardware/gnss/2.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
+ sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1;
+ bool mTracking;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H