aboutsummaryrefslogtreecommitdiff
path: root/gps/android
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
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')
-rw-r--r--gps/android/1.0/AGnss.cpp203
-rw-r--r--gps/android/1.0/AGnss.h79
-rw-r--r--gps/android/1.0/AGnssRil.cpp115
-rw-r--r--gps/android/1.0/AGnssRil.h83
-rw-r--r--gps/android/1.0/Android.mk99
-rw-r--r--gps/android/1.0/Gnss.cpp346
-rw-r--r--gps/android/1.0/Gnss.h143
-rw-r--r--gps/android/1.0/GnssBatching.cpp130
-rw-r--r--gps/android/1.0/GnssBatching.h80
-rw-r--r--gps/android/1.0/GnssConfiguration.cpp225
-rw-r--r--gps/android/1.0/GnssConfiguration.h71
-rw-r--r--gps/android/1.0/GnssDebug.cpp173
-rw-r--r--gps/android/1.0/GnssDebug.h59
-rw-r--r--gps/android/1.0/GnssGeofencing.cpp141
-rw-r--r--gps/android/1.0/GnssGeofencing.h91
-rw-r--r--gps/android/1.0/GnssMeasurement.cpp101
-rw-r--r--gps/android/1.0/GnssMeasurement.h77
-rw-r--r--gps/android/1.0/GnssNi.cpp85
-rw-r--r--gps/android/1.0/GnssNi.h75
-rw-r--r--gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc4
-rw-r--r--gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml35
-rw-r--r--gps/android/1.0/location_api/BatchingAPIClient.cpp197
-rw-r--r--gps/android/1.0/location_api/BatchingAPIClient.h75
-rw-r--r--gps/android/1.0/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/1.0/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/1.0/location_api/GnssAPIClient.cpp565
-rw-r--r--gps/android/1.0/location_api/GnssAPIClient.h110
-rw-r--r--gps/android/1.0/location_api/LocationUtil.cpp274
-rw-r--r--gps/android/1.0/location_api/LocationUtil.h57
-rw-r--r--gps/android/1.0/location_api/MeasurementAPIClient.cpp276
-rw-r--r--gps/android/1.0/location_api/MeasurementAPIClient.h78
-rw-r--r--gps/android/1.0/service.cpp85
-rw-r--r--gps/android/1.1/AGnss.cpp203
-rw-r--r--gps/android/1.1/AGnss.h79
-rw-r--r--gps/android/1.1/AGnssRil.cpp115
-rw-r--r--gps/android/1.1/AGnssRil.h83
-rw-r--r--gps/android/1.1/Android.mk101
-rw-r--r--gps/android/1.1/Gnss.cpp466
-rw-r--r--gps/android/1.1/Gnss.h154
-rw-r--r--gps/android/1.1/GnssBatching.cpp130
-rw-r--r--gps/android/1.1/GnssBatching.h80
-rw-r--r--gps/android/1.1/GnssConfiguration.cpp308
-rw-r--r--gps/android/1.1/GnssConfiguration.h78
-rw-r--r--gps/android/1.1/GnssDebug.cpp175
-rw-r--r--gps/android/1.1/GnssDebug.h59
-rw-r--r--gps/android/1.1/GnssGeofencing.cpp141
-rw-r--r--gps/android/1.1/GnssGeofencing.h91
-rw-r--r--gps/android/1.1/GnssMeasurement.cpp134
-rw-r--r--gps/android/1.1/GnssMeasurement.h83
-rw-r--r--gps/android/1.1/GnssNi.cpp85
-rw-r--r--gps/android/1.1/GnssNi.h75
-rw-r--r--gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc4
-rw-r--r--gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml35
-rw-r--r--gps/android/1.1/location_api/BatchingAPIClient.cpp197
-rw-r--r--gps/android/1.1/location_api/BatchingAPIClient.h75
-rw-r--r--gps/android/1.1/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/1.1/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/1.1/location_api/GnssAPIClient.cpp565
-rw-r--r--gps/android/1.1/location_api/GnssAPIClient.h110
-rw-r--r--gps/android/1.1/location_api/LocationUtil.cpp274
-rw-r--r--gps/android/1.1/location_api/LocationUtil.h57
-rw-r--r--gps/android/1.1/location_api/MeasurementAPIClient.cpp332
-rw-r--r--gps/android/1.1/location_api/MeasurementAPIClient.h85
-rw-r--r--gps/android/1.1/service.cpp85
-rw-r--r--gps/android/2.0/AGnss.cpp209
-rw-r--r--gps/android/2.0/AGnss.h77
-rw-r--r--gps/android/2.0/AGnssRil.cpp135
-rw-r--r--gps/android/2.0/AGnssRil.h84
-rw-r--r--gps/android/2.0/Android.mk112
-rw-r--r--gps/android/2.0/Gnss.cpp677
-rw-r--r--gps/android/2.0/Gnss.h187
-rw-r--r--gps/android/2.0/GnssBatching.cpp163
-rw-r--r--gps/android/2.0/GnssBatching.h84
-rw-r--r--gps/android/2.0/GnssConfiguration.cpp317
-rw-r--r--gps/android/2.0/GnssConfiguration.h80
-rw-r--r--gps/android/2.0/GnssDebug.cpp299
-rw-r--r--gps/android/2.0/GnssDebug.h62
-rw-r--r--gps/android/2.0/GnssGeofencing.cpp141
-rw-r--r--gps/android/2.0/GnssGeofencing.h91
-rw-r--r--gps/android/2.0/GnssMeasurement.cpp175
-rw-r--r--gps/android/2.0/GnssMeasurement.h87
-rw-r--r--gps/android/2.0/GnssNi.cpp85
-rw-r--r--gps/android/2.0/GnssNi.h75
-rw-r--r--gps/android/2.0/GnssVisibilityControl.cpp169
-rw-r--r--gps/android/2.0/GnssVisibilityControl.h90
-rw-r--r--gps/android/2.0/MeasurementCorrections.cpp73
-rw-r--r--gps/android/2.0/MeasurementCorrections.h77
-rw-r--r--gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc4
-rw-r--r--gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml36
-rw-r--r--gps/android/2.0/location_api/BatchingAPIClient.cpp251
-rw-r--r--gps/android/2.0/location_api/BatchingAPIClient.h82
-rw-r--r--gps/android/2.0/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/2.0/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/2.0/location_api/GnssAPIClient.cpp728
-rw-r--r--gps/android/2.0/location_api/GnssAPIClient.h115
-rw-r--r--gps/android/2.0/location_api/LocationUtil.cpp334
-rw-r--r--gps/android/2.0/location_api/LocationUtil.h60
-rw-r--r--gps/android/2.0/location_api/MeasurementAPIClient.cpp507
-rw-r--r--gps/android/2.0/location_api/MeasurementAPIClient.h90
-rw-r--r--gps/android/2.0/service.cpp81
-rw-r--r--gps/android/2.1/AGnss.cpp209
-rw-r--r--gps/android/2.1/AGnss.h78
-rw-r--r--gps/android/2.1/AGnssRil.cpp135
-rw-r--r--gps/android/2.1/AGnssRil.h84
-rw-r--r--gps/android/2.1/Android.mk116
-rw-r--r--gps/android/2.1/Gnss.cpp800
-rw-r--r--gps/android/2.1/Gnss.h193
-rw-r--r--gps/android/2.1/GnssAntennaInfo.cpp202
-rw-r--r--gps/android/2.1/GnssAntennaInfo.h90
-rw-r--r--gps/android/2.1/GnssBatching.cpp163
-rw-r--r--gps/android/2.1/GnssBatching.h84
-rw-r--r--gps/android/2.1/GnssConfiguration.cpp408
-rw-r--r--gps/android/2.1/GnssConfiguration.h88
-rw-r--r--gps/android/2.1/GnssDebug.cpp299
-rw-r--r--gps/android/2.1/GnssDebug.h62
-rw-r--r--gps/android/2.1/GnssGeofencing.cpp141
-rw-r--r--gps/android/2.1/GnssGeofencing.h91
-rw-r--r--gps/android/2.1/GnssMeasurement.cpp211
-rw-r--r--gps/android/2.1/GnssMeasurement.h93
-rw-r--r--gps/android/2.1/GnssNi.cpp85
-rw-r--r--gps/android/2.1/GnssNi.h75
-rw-r--r--gps/android/2.1/GnssVisibilityControl.cpp169
-rw-r--r--gps/android/2.1/GnssVisibilityControl.h90
-rw-r--r--gps/android/2.1/MeasurementCorrections.cpp199
-rw-r--r--gps/android/2.1/MeasurementCorrections.h106
-rw-r--r--gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc4
-rwxr-xr-xgps/android/2.1/android.hardware.gnss@2.1-service-qti.xml36
-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
-rwxr-xr-xgps/android/2.1/service.cpp81
-rw-r--r--gps/android/Android.mk2
-rw-r--r--gps/android/utils/Android.bp37
-rw-r--r--gps/android/utils/battery_listener.cpp280
-rw-r--r--gps/android/utils/battery_listener.h32
142 files changed, 23105 insertions, 0 deletions
diff --git a/gps/android/1.0/AGnss.cpp b/gps/android/1.0/AGnss.cpp
new file mode 100644
index 0000000..79f665c
--- /dev/null
+++ b/gps/android/1.0/AGnss.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status){
+ if (nullptr != spAGnss) {
+ spAGnss->statusIpV4Cb(status);
+ }
+}
+
+void AGnss::statusIpV4Cb(AGnssExtStatusIpV4 status) {
+ IAGnssCallback::AGnssStatusIpV4 st = {};
+
+ switch (status.type) {
+ case LOC_AGPS_TYPE_SUPL:
+ st.type = IAGnssCallback::AGnssType::TYPE_SUPL;
+ break;
+ case LOC_AGPS_TYPE_C2K:
+ st.type = IAGnssCallback::AGnssType::TYPE_C2K;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", status.type);
+ return;
+ }
+
+ switch (status.status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status.status);
+ return;
+ }
+ st.ipV4Addr = status.ipV4Addr;
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusIpV4Cb(st);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::TYPE_SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::TYPE_C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<int>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/AGnss.h b/gps/android/1.0/AGnss.h
new file mode 100644
index 0000000..cdd5931
--- /dev/null
+++ b/gps/android/1.0/AGnss.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
+
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
diff --git a/gps/android/1.0/AGnssRil.cpp b/gps/android/1.0/AGnssRil.cpp
new file mode 100644
index 0000000..d7f30eb
--- /dev/null
+++ b/gps/android/1.0/AGnssRil.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/AGnssRil.h b/gps/android/1.0/AGnssRil.h
new file mode 100644
index 0000000..7f18c57
--- /dev/null
+++ b/gps/android/1.0/AGnssRil.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, NetworkType type, bool roaming) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
diff --git a/gps/android/1.0/Android.mk b/gps/android/1.0/Android.mk
new file mode 100644
index 0000000..797ecce
--- /dev/null
+++ b/gps/android/1.0/Android.mk
@@ -0,0 +1,99 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssMeasurement.cpp \
+ GnssNi.cpp \
+ GnssConfiguration.cpp \
+ GnssDebug.cpp \
+ AGnssRil.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/LocationUtil.cpp \
+ location_api/GnssAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.0-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@1.0-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/1.0/Gnss.cpp b/gps/android/1.0/Gnss.cpp
new file mode 100644
index 0000000..308cc7c
--- /dev/null
+++ b/gps/android/1.0/Gnss.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+static sp<Gnss> sGnss;
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->stop();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not ");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+ }
+ if (mApi == nullptr) {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ }
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (const GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ mAGnssIface = new AGnss(this);
+ return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNi = new GnssNi(this);
+ return mGnssNi;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssGeofencingIface = new GnssGeofencing();
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ mGnssBatching = new GnssBatching();
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssDebug = new GnssDebug(this);
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ mGnssRil = new AGnssRil(this);
+ return mGnssRil;
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/Gnss.h b/gps/android/1.0/Gnss.h
new file mode 100644
index 0000000..900a510
--- /dev/null
+++ b/gps/android/1.0/Gnss.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <GnssAPIClient.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<AGnss> mAGnssIface = nullptr;
+ sp<GnssNi> mGnssNi = nullptr;
+ sp<GnssMeasurement> mGnssMeasurement = nullptr;
+ sp<GnssConfiguration> mGnssConfig = nullptr;
+ sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<GnssBatching> mGnssBatching = nullptr;
+ sp<IGnssDebug> mGnssDebug = nullptr;
+ sp<AGnssRil> mGnssRil = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
diff --git a/gps/android/1.0/GnssBatching.cpp b/gps/android/1.0/GnssBatching.cpp
new file mode 100644
index 0000000..f92697f
--- /dev/null
+++ b/gps/android/1.0/GnssBatching.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssBatching.h b/gps/android/1.0/GnssBatching.h
new file mode 100644
index 0000000..8fab857
--- /dev/null
+++ b/gps/android/1.0/GnssBatching.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/gps/android/1.0/GnssConfiguration.cpp b/gps/android/1.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..a7f64fa
--- /dev/null
+++ b/gps/android/1.0/GnssConfiguration.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ config.suplEmergencyServices = (enabled ?
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES :
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssConfiguration.h b/gps/android/1.0/GnssConfiguration.h
new file mode 100644
index 0000000..d0e2ba8
--- /dev/null
+++ b/gps/android/1.0/GnssConfiguration.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
diff --git a/gps/android/1.0/GnssDebug.cpp b/gps/android/1.0/GnssDebug.cpp
new file mode 100644
index 0000000..ead72e1
--- /dev/null
+++ b/gps/android/1.0/GnssDebug.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0 ||
+ data.time.timeUncertaintyNs > (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ SatelliteData s = { };
+ std::vector<SatelliteData> s_array = { };
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssDebug.h b/gps/android/1.0/GnssDebug.h
new file mode 100644
index 0000000..a7116cb
--- /dev/null
+++ b/gps/android/1.0/GnssDebug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+ * These declarations were generated from IGnssDebug.hal.
+ */
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
diff --git a/gps/android/1.0/GnssGeofencing.cpp b/gps/android/1.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..4be6d8a
--- /dev/null
+++ b/gps/android/1.0/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGE("%s]: mApi is NOT nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssGeofencing.h b/gps/android/1.0/GnssGeofencing.h
new file mode 100644
index 0000000..db5f9d2
--- /dev/null
+++ b/gps/android/1.0/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
diff --git a/gps/android/1.0/GnssMeasurement.cpp b/gps/android/1.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..7af9e27
--- /dev/null
+++ b/gps/android/1.0/GnssMeasurement.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include <MeasurementAPIClient.h>
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+
+Return<IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ mApi->measurementClose();
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssMeasurement.h b/gps/android/1.0/GnssMeasurement.h
new file mode 100644
index 0000000..4247dbf
--- /dev/null
+++ b/gps/android/1.0/GnssMeasurement.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ MeasurementAPIClient* mApi;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
diff --git a/gps/android/1.0/GnssNi.cpp b/gps/android/1.0/GnssNi.cpp
new file mode 100644
index 0000000..d06cc20
--- /dev/null
+++ b/gps/android/1.0/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssNi.h b/gps/android/1.0/GnssNi.h
new file mode 100644
index 0000000..90f62d5
--- /dev/null
+++ b/gps/android/1.0/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
diff --git a/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc
new file mode 100644
index 0000000..1fbd893
--- /dev/null
+++ b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml
new file mode 100644
index 0000000..46bcffb
--- /dev/null
+++ b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml
@@ -0,0 +1,35 @@
+<!-- Copyright (c) 2019, 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.0::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/1.0/location_api/BatchingAPIClient.cpp b/gps/android/1.0/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..94a234d
--- /dev/null
+++ b/gps/android/1.0/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,197 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <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 V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(callback),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ if (mGnssBatchingCbIface != nullptr) {
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ }
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<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*/)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (mGnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/BatchingAPIClient.h b/gps/android/1.0/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..c3b0a7b
--- /dev/null
+++ b/gps/android/1.0/location_api/BatchingAPIClient.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_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();
+
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.cpp b/gps/android/1.0/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..774a049
--- /dev/null
+++ b/gps/android/1.0/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<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]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<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 V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.h b/gps/android/1.0/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..b6a009b
--- /dev/null
+++ b/gps/android/1.0/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+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 V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/1.0/location_api/GnssAPIClient.cpp b/gps/android/1.0/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..4247258
--- /dev/null
+++ b/gps/android/1.0/location_api/GnssAPIClient.cpp
@@ -0,0 +1,565 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <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 V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnss;
+using ::android::hardware::gnss::V1_0::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
+
+GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+ }
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+
+ locationCallbacks.gnssNiCb = nullptr;
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
+ onGnssNiCb(id, gnssNiNotification);
+ };
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+ }
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+ }
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<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;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+ auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+ gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<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++) {
+ IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
+ convertGnssSvid(in.gnssSvs[i], info.svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
+ info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ info.elevationDegrees = in.gnssSvs[i].elevation;
+ info.azimuthDegrees = in.gnssSvs[i].azimuth;
+ info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/GnssAPIClient.h b/gps/android/1.0/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..427b0db
--- /dev/null
+++ b/gps/android/1.0/location_api/GnssAPIClient.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/1.0/IGnssCallback.h>
+#include <android/hardware/gnss/1.0/IGnssNiCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+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 GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/1.0/location_api/LocationUtil.cpp b/gps/android/1.0/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..870a8aa
--- /dev/null
+++ b/gps/android/1.0/location_api/LocationUtil.cpp
@@ -0,0 +1,274 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+
+void convertGnssLocation(Location& in, GnssLocation& out)
+{
+ memset(&out, 0, sizeof(GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(const GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch(in.type){
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/LocationUtil.h b/gps/android/1.0/location_api/LocationUtil.h
new file mode 100644
index 0000000..f6760e5
--- /dev/null
+++ b/gps/android/1.0/location_api/LocationUtil.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/1.0/types.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.cpp b/gps/android/1.0/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..9b23308
--- /dev/null
+++ b/gps/android/1.0/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,276 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+ if (mGnssMeasurementCbIface != nullptr) {
+ locationCallbacks.gnssMeasurementsCb =
+ [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+ onGnssMeasurementsCb(gnssMeasurementsNotification);
+ };
+ }
+
+ locAPISetCallbacks(locationCallbacks);
+
+ TrackingOptions options = {};
+ memset(&options, 0, sizeof(TrackingOptions));
+ options.size = sizeof(TrackingOptions);
+ options.minInterval = 1000;
+ options.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ mTracking = true;
+ LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+ locAPIStartTracking(options);
+ return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ mTracking = false;
+ locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+ GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+ LOC_LOGD("%s]: (count: %zu active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface != nullptr) {
+ V1_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+ memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<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(IGnssMeasurementCallback::GnssClock));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<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);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.h b/gps/android/1.0/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..225deac
--- /dev/null
+++ b/gps/android/1.0/location_api/MeasurementAPIClient.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.0/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking();
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+
+ bool mTracking;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/1.0/service.cpp b/gps/android/1.0/service.cpp
new file mode 100644
index 0000000..2a6f60f
--- /dev/null
+++ b/gps/android/1.0/service.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@1.0-service-qti"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V1_0::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ if (vendorEnhanced) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGE("LOC_HIDL_VERSION not defined.");
+ #endif
+ }
+
+ joinRpcThreadpool();
+
+ } else {
+ ALOGE("Error while registering IGnss 1.0 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/1.1/AGnss.cpp b/gps/android/1.1/AGnss.cpp
new file mode 100644
index 0000000..d8f9706
--- /dev/null
+++ b/gps/android/1.1/AGnss.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status){
+ if (nullptr != spAGnss) {
+ spAGnss->statusIpV4Cb(status);
+ }
+}
+
+void AGnss::statusIpV4Cb(AGnssExtStatusIpV4 status) {
+ IAGnssCallback::AGnssStatusIpV4 st = {};
+
+ switch (status.type) {
+ case LOC_AGPS_TYPE_SUPL:
+ st.type = IAGnssCallback::AGnssType::TYPE_SUPL;
+ break;
+ case LOC_AGPS_TYPE_C2K:
+ st.type = IAGnssCallback::AGnssType::TYPE_C2K;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", status.type);
+ return;
+ }
+
+ switch (status.status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status.status);
+ return;
+ }
+ st.ipV4Addr = status.ipV4Addr;
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusIpV4Cb(st);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::TYPE_SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::TYPE_C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<int>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/AGnss.h b/gps/android/1.1/AGnss.h
new file mode 100644
index 0000000..4b599b9
--- /dev/null
+++ b/gps/android/1.1/AGnss.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
+
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
diff --git a/gps/android/1.1/AGnssRil.cpp b/gps/android/1.1/AGnssRil.cpp
new file mode 100644
index 0000000..95c8d63
--- /dev/null
+++ b/gps/android/1.1/AGnssRil.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/AGnssRil.h b/gps/android/1.1/AGnssRil.h
new file mode 100644
index 0000000..5c9298a
--- /dev/null
+++ b/gps/android/1.1/AGnssRil.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, NetworkType type, bool roaming) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
diff --git a/gps/android/1.1/Android.mk b/gps/android/1.1/Android.mk
new file mode 100644
index 0000000..66abd06
--- /dev/null
+++ b/gps/android/1.1/Android.mk
@@ -0,0 +1,101 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.1-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssMeasurement.cpp \
+ GnssNi.cpp \
+ GnssConfiguration.cpp \
+ GnssDebug.cpp \
+ AGnssRil.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/LocationUtil.cpp \
+ location_api/GnssAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.1-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.1-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@1.1-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/1.1/Gnss.cpp b/gps/android/1.1/Gnss.cpp
new file mode 100644
index 0000000..537f6a6
--- /dev/null
+++ b/gps/android/1.1/Gnss.cpp
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->stop();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+ }
+ if (mApi == nullptr) {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ }
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (const GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ mAGnssIface = new AGnss(this);
+ return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNi = new GnssNi(this);
+ return mGnssNi;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssGeofencingIface = new GnssGeofencing();
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ mGnssBatching = new GnssBatching();
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssDebug = new GnssDebug(this);
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ mGnssRil = new AGnssRil(this);
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ callback->gnssNameCb(getVersionString());
+ mGnssCbIface_1_1 = callback;
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+ return setCallback(callback);
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/Gnss.h b/gps/android/1.1/Gnss.h
new file mode 100644
index 0000000..15645eb
--- /dev/null
+++ b/gps/android/1.1/Gnss.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017-2018-2018-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <GnssAPIClient.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<AGnss> mAGnssIface = nullptr;
+ sp<GnssNi> mGnssNi = nullptr;
+ sp<GnssMeasurement> mGnssMeasurement = nullptr;
+ sp<GnssConfiguration> mGnssConfig = nullptr;
+ sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<GnssBatching> mGnssBatching = nullptr;
+ sp<IGnssDebug> mGnssDebug = nullptr;
+ sp<AGnssRil> mGnssRil = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
diff --git a/gps/android/1.1/GnssBatching.cpp b/gps/android/1.1/GnssBatching.cpp
new file mode 100644
index 0000000..8ab264d
--- /dev/null
+++ b/gps/android/1.1/GnssBatching.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssBatching.h b/gps/android/1.1/GnssBatching.h
new file mode 100644
index 0000000..8e235d8
--- /dev/null
+++ b/gps/android/1.1/GnssBatching.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
diff --git a/gps/android/1.1/GnssConfiguration.cpp b/gps/android/1.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..ad255d1
--- /dev/null
+++ b/gps/android/1.1/GnssConfiguration.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ config.suplEmergencyServices = (enabled ?
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES :
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %d", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssConfiguration.h b/gps/android/1.1/GnssConfiguration.h
new file mode 100644
index 0000000..daea159
--- /dev/null
+++ b/gps/android/1.1/GnssConfiguration.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/1.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
diff --git a/gps/android/1.1/GnssDebug.cpp b/gps/android/1.1/GnssDebug.cpp
new file mode 100644
index 0000000..f164c54
--- /dev/null
+++ b/gps/android/1.1/GnssDebug.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ SatelliteData s = { };
+ std::vector<SatelliteData> s_array = { };
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssDebug.h b/gps/android/1.1/GnssDebug.h
new file mode 100644
index 0000000..cb818ac
--- /dev/null
+++ b/gps/android/1.1/GnssDebug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+ * These declarations were generated from IGnssDebug.hal.
+ */
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
diff --git a/gps/android/1.1/GnssGeofencing.cpp b/gps/android/1.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..a4aaf88
--- /dev/null
+++ b/gps/android/1.1/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssGeofencing.h b/gps/android/1.1/GnssGeofencing.h
new file mode 100644
index 0000000..94a73de
--- /dev/null
+++ b/gps/android/1.1/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
diff --git a/gps/android/1.1/GnssMeasurement.cpp b/gps/android/1.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..6f8c14d
--- /dev/null
+++ b/gps/android/1.1/GnssMeasurement.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include <MeasurementAPIClient.h>
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+
+Return<IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssMeasurement.h b/gps/android/1.1/GnssMeasurement.h
new file mode 100644
index 0000000..373f0d0
--- /dev/null
+++ b/gps/android/1.1/GnssMeasurement.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssMeasurement;
+using ::android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ MeasurementAPIClient* mApi;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
diff --git a/gps/android/1.1/GnssNi.cpp b/gps/android/1.1/GnssNi.cpp
new file mode 100644
index 0000000..5ce9569
--- /dev/null
+++ b/gps/android/1.1/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssNi.h b/gps/android/1.1/GnssNi.h
new file mode 100644
index 0000000..6733e5b
--- /dev/null
+++ b/gps/android/1.1/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
diff --git a/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc
new file mode 100644
index 0000000..bd65584
--- /dev/null
+++ b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.1-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml
new file mode 100644
index 0000000..c9c83fb
--- /dev/null
+++ b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml
@@ -0,0 +1,35 @@
+<!-- Copyright (c) 2019, 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/1.1/location_api/BatchingAPIClient.cpp b/gps/android/1.1/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..6ec27a9
--- /dev/null
+++ b/gps/android/1.1/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,197 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <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 V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(callback),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ if (mGnssBatchingCbIface != nullptr) {
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ }
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<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*/)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (mGnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/BatchingAPIClient.h b/gps/android/1.1/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..4c90626
--- /dev/null
+++ b/gps/android/1.1/location_api/BatchingAPIClient.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_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();
+
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/1.1/location_api/GeofenceAPIClient.cpp b/gps/android/1.1/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..93d175e
--- /dev/null
+++ b/gps/android/1.1/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_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]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<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 V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/GeofenceAPIClient.h b/gps/android/1.1/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..0ffff91
--- /dev/null
+++ b/gps/android/1.1/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_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 V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/1.1/location_api/GnssAPIClient.cpp b/gps/android/1.1/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..a2c4eec
--- /dev/null
+++ b/gps/android/1.1/location_api/GnssAPIClient.cpp
@@ -0,0 +1,565 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <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 V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnss;
+using ::android::hardware::gnss::V1_0::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
+
+GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+ }
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+
+ locationCallbacks.gnssNiCb = nullptr;
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
+ onGnssNiCb(id, gnssNiNotification);
+ };
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+ }
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+ }
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<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;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+ auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+ gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<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++) {
+ IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
+ convertGnssSvid(in.gnssSvs[i], info.svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
+ info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ info.elevationDegrees = in.gnssSvs[i].elevation;
+ info.azimuthDegrees = in.gnssSvs[i].azimuth;
+ info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/GnssAPIClient.h b/gps/android/1.1/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..3829265
--- /dev/null
+++ b/gps/android/1.1/location_api/GnssAPIClient.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <android/hardware/gnss/1.1/IGnssCallback.h>
+#include <android/hardware/gnss/1.0/IGnssNiCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_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 GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/1.1/location_api/LocationUtil.cpp b/gps/android/1.1/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..26fd920
--- /dev/null
+++ b/gps/android/1.1/location_api/LocationUtil.cpp
@@ -0,0 +1,274 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+
+void convertGnssLocation(Location& in, GnssLocation& out)
+{
+ memset(&out, 0, sizeof(GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(const GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch(in.type){
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { //OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/LocationUtil.h b/gps/android/1.1/location_api/LocationUtil.h
new file mode 100644
index 0000000..af3c93f
--- /dev/null
+++ b/gps/android/1.1/location_api/LocationUtil.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/1.0/types.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/1.1/location_api/MeasurementAPIClient.cpp b/gps/android/1.1/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..a87ae6d
--- /dev/null
+++ b/gps/android/1.1/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,332 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mGnssMeasurementCbIface_1_1(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface_1_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_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: %zu active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ sp<IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+ } else if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface_1_1 != nullptr) {
+ 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(IGnssMeasurementCallback::GnssMeasurement));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<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(IGnssMeasurementCallback::GnssClock));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<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,
+ IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/MeasurementAPIClient.h b/gps/android/1.1/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..5fb307c
--- /dev/null
+++ b/gps/android/1.1/location_api/MeasurementAPIClient.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_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<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<IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+
+ bool mTracking;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/1.1/service.cpp b/gps/android/1.1/service.cpp
new file mode 100644
index 0000000..0cb91f7
--- /dev/null
+++ b/gps/android/1.1/service.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@1.1-service-qti"
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V1_1::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ if (vendorEnhanced) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGE("LOC_HIDL_VERSION not defined.");
+ #endif
+ }
+
+ joinRpcThreadpool();
+
+ } else {
+ ALOGE("Error while registering IGnss 1.1 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/2.0/AGnss.cpp b/gps/android/2.0/AGnss.cpp
new file mode 100644
index 0000000..a48f1a0
--- /dev/null
+++ b/gps/android/2.0/AGnss.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
+ if (nullptr != spAGnss) {
+ spAGnss->statusCb(status.type, status.status);
+ }
+}
+
+void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {
+
+ V2_0::IAGnssCallback::AGnssType aType;
+ IAGnssCallback::AGnssStatusValue aStatus;
+
+ switch (type) {
+ case LOC_AGPS_TYPE_SUPL:
+ aType = IAGnssCallback::AGnssType::SUPL;
+ break;
+ case LOC_AGPS_TYPE_SUPL_ES:
+ aType = IAGnssCallback::AGnssType::SUPL_EIMS;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", type);
+ return;
+ }
+
+ switch (status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status);
+ return;
+ }
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ }
+ else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/AGnss.h b/gps/android/2.0/AGnss.h
new file mode 100644
index 0000000..c442327
--- /dev/null
+++ b/gps/android/2.0/AGnss.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+
+#include <android/hardware/gnss/2.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public V2_0::IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusCb(AGpsExtType type, LocAGpsStatusValue status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
diff --git a/gps/android/2.0/AGnssRil.cpp b/gps/android/2.0/AGnssRil.cpp
new file mode 100644
index 0000000..d8005e4
--- /dev/null
+++ b/gps/android/2.0/AGnssRil.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
+ ENTRY_LOG_CALLFLOW();
+ std::string apn = attributes.apn;
+ if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ bool roaming = false;
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
+ typeout = loc_core::TYPE_WIFI;
+ } else {
+ typeout = loc_core::TYPE_MOBILE;
+ }
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
+ roaming = false;
+ }
+ LOC_LOGd("apn string received is: %s", apn.c_str());
+ mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
+ typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/AGnssRil.h b/gps/android/2.0/AGnssRil.h
new file mode 100644
index 0000000..a04d8aa
--- /dev/null
+++ b/gps/android/2.0/AGnssRil.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/2.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public V2_0::IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
+ Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
diff --git a/gps/android/2.0/Android.mk b/gps/android/2.0/Android.mk
new file mode 100644
index 0000000..c0b91ae
--- /dev/null
+++ b/gps/android/2.0/Android.mk
@@ -0,0 +1,112 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.0-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ AGnssRil.cpp \
+ GnssMeasurement.cpp \
+ GnssConfiguration.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssNi.cpp \
+ GnssDebug.cpp \
+ MeasurementCorrections.cpp \
+ GnssVisibilityControl.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/GnssAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/LocationUtil.cpp \
+
+ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
+LOCAL_CFLAGS += \
+ -DGNSS_HIDL_LEGACY_MEASURMENTS
+endif
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss.measurement_corrections@1.0 \
+ android.hardware.gnss.visibility_control@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.health@2.1 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.0-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.0-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@2.0-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/2.0/Gnss.cpp b/gps/android/2.0/Gnss.cpp
new file mode 100644
index 0000000..823ef6e
--- /dev/null
+++ b/gps/android/2.0/Gnss.cpp
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include "LocationUtil.h"
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi != nullptr) {
+ return mApi;
+ }
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_0);
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
+ } else if (mGnssCbIface != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ } else {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+
+ // In case where previous call to setCallback_1_1 or setCallback_2_0, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+
+
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssStop();
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssGeofencingIface == nullptr) {
+ mGnssGeofencingIface = new GnssGeofencing();
+ }
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssBatching == nullptr) {
+ mGnssBatching = new GnssBatching();
+ }
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback or setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+
+
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_1_1 = callback;
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback or setCallback_1_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_0 = callback;
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mAGnssIface_2_0 == nullptr) {
+ mAGnssIface_2_0 = new AGnss(this);
+ }
+ return mAGnssIface_2_0;
+}
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>>
+ Gnss::getExtensionMeasurementCorrections() {
+ // We do not support, so return nullptr to pass VTS
+ return nullptr;
+}
+Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ Gnss::getExtensionVisibilityControl() {
+ ENTRY_LOG_CALLFLOW();
+ if (mVisibCtrl == nullptr) {
+ mVisibCtrl = new GnssVisibilityControl(this);
+ }
+ return mVisibCtrl;
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ return nullptr;
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/Gnss.h b/gps/android/2.0/Gnss.h
new file mode 100644
index 0000000..a403d61
--- /dev/null
+++ b/gps/android/2.0/Gnss.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssConfiguration.h>
+#include <GnssMeasurement.h>
+#include <GnssBatching.h>
+#include <GnssGeofencing.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <MeasurementCorrections.h>
+#include <GnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "GnssAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using ::android::hardware::gnss::measurement_corrections::V1_0::implementation::MeasurementCorrections;
+using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+ Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+ Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+ Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+
+ Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>>
+ getExtensionMeasurementCorrections() override;
+ Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+
+ Return<bool> injectBestLocation_2_0(const ::android::hardware::gnss::V2_0::GnssLocation& location) override;
+
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+
+
+ /**
+ * This method returns the IGnssVisibilityControl interface.
+ *
+ * @return visibilityControlIface Handle to the IGnssVisibilityControl interface.
+ */
+ Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ getExtensionVisibilityControl() override;
+
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<V1_0::IGnssNi> mGnssNi = nullptr;
+ sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<V1_0::IAGnss> mAGnssIface = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
+ sp<V2_0::IAGnssRil> mGnssRil = nullptr;
+ sp<V2_0::IGnssMeasurement> mGnssMeasurement = nullptr;
+ sp<V2_0::IGnssConfiguration> mGnssConfig = nullptr;
+ sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
+ sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
+ sp<IMeasurementCorrections> mGnssMeasCorr = nullptr;
+ sp<IGnssVisibilityControl> mVisibCtrl = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
diff --git a/gps/android/2.0/GnssBatching.cpp b/gps/android/2.0/GnssBatching.cpp
new file mode 100644
index 0000000..6a2a09e
--- /dev/null
+++ b/gps/android/2.0/GnssBatching.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mApi != nullptr) {
+ mApi->stopSession();
+ }
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface = nullptr;
+ }
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface_2_0 = nullptr;
+ }
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface_2_0 = callback;
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssBatching.h b/gps/android/2.0/GnssBatching.h
new file mode 100644
index 0000000..4c8d1db
--- /dev/null
+++ b/gps/android/2.0/GnssBatching.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+ Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0 = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
diff --git a/gps/android/2.0/GnssConfiguration.cpp b/gps/android/2.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..55a70dc
--- /dev/null
+++ b/gps/android/2.0/GnssConfiguration.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include "ContextBase.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using namespace loc_core;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ // deprecated function. Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ mGnss->updateConfiguration(config);
+ // Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnss == nullptr) {
+ LOC_LOGe("mGnss is nullptr");
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ config.emergencyExtensionSeconds = emergencyExtensionSeconds;
+
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssConfiguration.h b/gps/android/2.0/GnssConfiguration.h
new file mode 100644
index 0000000..c3de2c9
--- /dev/null
+++ b/gps/android/2.0/GnssConfiguration.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public V2_0::IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+ Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
diff --git a/gps/android/2.0/GnssDebug.cpp b/gps/android/2.0/GnssDebug.cpp
new file mode 100644
index 0000000..dc0d9f4
--- /dev/null
+++ b/gps/android/2.0/GnssDebug.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V1_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V1_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V1_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+Return<void> GnssDebug::getDebugData_2_0(getDebugData_2_0_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V2_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ }
+ else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V2_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V2_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.v1_0.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.v1_0.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.v1_0.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.v1_0.ephemerisHealth);
+
+ s.v1_0.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.v1_0.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.v1_0.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssDebug.h b/gps/android/2.0/GnssDebug.h
new file mode 100644
index 0000000..8d75bea
--- /dev/null
+++ b/gps/android/2.0/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/2.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+ // Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow.
+ Return<void> getDebugData_2_0(getDebugData_2_0_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
diff --git a/gps/android/2.0/GnssGeofencing.cpp b/gps/android/2.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..b6fc94b
--- /dev/null
+++ b/gps/android/2.0/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssGeofencing.h b/gps/android/2.0/GnssGeofencing.h
new file mode 100644
index 0000000..caa56d0
--- /dev/null
+++ b/gps/android/2.0/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
diff --git a/gps/android/2.0/GnssMeasurement.cpp b/gps/android/2.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..6cb55ca
--- /dev/null
+++ b/gps/android/2.0/GnssMeasurement.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include "GnssMeasurement.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+}
+
+void GnssMeasurement::clearInterfaces() {
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ }
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ clearInterfaces();
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_0 = callback;
+ mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_0(callback, powerMode);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssMeasurement.h b/gps/android/2.0/GnssMeasurement.h
new file mode 100644
index 0000000..7fa66b4
--- /dev/null
+++ b/gps/android/2.0/GnssMeasurement.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public V2_0::IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
+ MeasurementAPIClient* mApi;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
diff --git a/gps/android/2.0/GnssNi.cpp b/gps/android/2.0/GnssNi.cpp
new file mode 100644
index 0000000..d65a488
--- /dev/null
+++ b/gps/android/2.0/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssNi.h b/gps/android/2.0/GnssNi.h
new file mode 100644
index 0000000..26e281f
--- /dev/null
+++ b/gps/android/2.0/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
diff --git a/gps/android/2.0/GnssVisibilityControl.cpp b/gps/android/2.0/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..5a8c697
--- /dev/null
+++ b/gps/android/2.0/GnssVisibilityControl.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019, 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 <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "GnssVisibilityControl.h"
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+static GnssVisibilityControl* spGnssVisibilityControl = nullptr;
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out);
+
+GnssVisibilityControl::GnssVisibilityControl(Gnss* gnss) : mGnss(gnss) {
+ spGnssVisibilityControl = this;
+}
+GnssVisibilityControl::~GnssVisibilityControl() {
+ spGnssVisibilityControl = nullptr;
+}
+
+void GnssVisibilityControl::nfwStatusCb(GnssNfwNotification notification) {
+ if (nullptr != spGnssVisibilityControl) {
+ spGnssVisibilityControl->statusCb(notification);
+ }
+}
+
+bool GnssVisibilityControl::isInEmergencySession() {
+ if (nullptr != spGnssVisibilityControl) {
+ return spGnssVisibilityControl->isE911Session();
+ }
+ return false;
+}
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out)
+{
+ memset(&out, 0, sizeof(IGnssVisibilityControlCallback::NfwNotification));
+ out.proxyAppPackageName = in.proxyAppPackageName;
+ out.protocolStack = (IGnssVisibilityControlCallback::NfwProtocolStack)in.protocolStack;
+ out.otherProtocolStackName = in.otherProtocolStackName;
+ out.requestor = (IGnssVisibilityControlCallback::NfwRequestor)in.requestor;
+ out.requestorId = in.requestorId;
+ out.responseType = (IGnssVisibilityControlCallback::NfwResponseType)in.responseType;
+ out.inEmergencyMode = in.inEmergencyMode;
+ out.isCachedLocation = in.isCachedLocation;
+}
+
+void GnssVisibilityControl::statusCb(GnssNfwNotification notification) {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ IGnssVisibilityControlCallback::NfwNotification nfwNotification;
+
+ // Convert from one structure to another
+ convertGnssNfwNotification(notification, nfwNotification);
+
+ auto r = mGnssVisibilityControlCbIface->nfwNotifyCb(nfwNotification);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+bool GnssVisibilityControl::isE911Session() {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ auto r = mGnssVisibilityControlCbIface->isInEmergencySession();
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ return false;
+ } else {
+ return (r);
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ return false;
+ }
+}
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+
+ /* If the vector is empty we need to disable all NFW clients
+ If there is at least one app in the vector we need to enable
+ all NFW clients */
+ if (0 == proxyApps.size()) {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(false);
+ } else {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(true);
+ }
+
+ return true;
+}
+/**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+Return<bool> GnssVisibilityControl::setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mGnssVisibilityControlCbIface = callback;
+
+ NfwCbInfo cbInfo = {};
+ cbInfo.visibilityControlCb = (void*)nfwStatusCb;
+ cbInfo.isInEmergencySession = (void*)isInEmergencySession;
+
+ mGnss->getGnssInterface()->nfwInit(cbInfo);
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssVisibilityControl.h b/gps/android/2.0/GnssVisibilityControl.h
new file mode 100644
index 0000000..9c26e38
--- /dev/null
+++ b/gps/android/2.0/GnssVisibilityControl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, 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 ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V2_0::implementation::Gnss;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+ GnssVisibilityControl(Gnss* gnss);
+ ~GnssVisibilityControl();
+
+ // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+ Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override;
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override;
+
+ void statusCb(GnssNfwNotification notification);
+ bool isE911Session();
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void nfwStatusCb(GnssNfwNotification notification);
+ static bool isInEmergencySession();
+
+private:
+ Gnss* mGnss = nullptr;
+ sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
diff --git a/gps/android/2.0/MeasurementCorrections.cpp b/gps/android/2.0/MeasurementCorrections.cpp
new file mode 100644
index 0000000..bb75073
--- /dev/null
+++ b/gps/android/2.0/MeasurementCorrections.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019-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_TAG "LocSvc_MeasurementCorrectionsInterface"
+
+#include <log_util.h>
+#include "MeasurementCorrections.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+MeasurementCorrections::MeasurementCorrections() {
+}
+
+MeasurementCorrections::~MeasurementCorrections() {
+}
+
+Return<bool> MeasurementCorrections::setCorrections(
+ const ::android::hardware::gnss::measurement_corrections::
+ V1_0::MeasurementCorrections& /*corrections*/) {
+ return true;
+}
+
+Return<bool> MeasurementCorrections::setCallback(
+ const sp<V1_0::IMeasurementCorrectionsCallback>& /*callback*/) {
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/MeasurementCorrections.h b/gps/android/2.0/MeasurementCorrections.h
new file mode 100644
index 0000000..96b1120
--- /dev/null
+++ b/gps/android/2.0/MeasurementCorrections.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019-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 ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
+#define ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
+
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+
+struct MeasurementCorrections : public IMeasurementCorrections {
+ MeasurementCorrections();
+ ~MeasurementCorrections();
+
+// Methods from ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections follow.
+Return<bool> setCorrections(
+ const ::android::hardware::gnss::measurement_corrections::
+ V1_0::MeasurementCorrections& corrections) override;
+
+Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
diff --git a/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc
new file mode 100644
index 0000000..ad46d5d
--- /dev/null
+++ b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@2.0-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml
new file mode 100644
index 0000000..ff9fb2c
--- /dev/null
+++ b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml
@@ -0,0 +1,36 @@
+<!-- Copyright (c) 2019, 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ <fqname>@2.0::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/2.0/location_api/BatchingAPIClient.cpp b/gps/android/2.0/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..766c37a
--- /dev/null
+++ b/gps/android/2.0/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,251 @@
+/* Copyright (c) 2017-2019, 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_0 {
+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_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/BatchingAPIClient.h b/gps/android/2.0/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..d2d9b4a
--- /dev/null
+++ b/gps/android/2.0/location_api/BatchingAPIClient.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2017-2019, 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_0 {
+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:
+ void setCallbacks();
+ ~BatchingAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/2.0/location_api/GeofenceAPIClient.cpp b/gps/android/2.0/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..a93c988
--- /dev/null
+++ b/gps/android/2.0/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2019, 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_0 {
+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_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/GeofenceAPIClient.h b/gps/android/2.0/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..5bce476
--- /dev/null
+++ b/gps/android/2.0/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2019, 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_0 {
+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_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/2.0/location_api/GnssAPIClient.cpp b/gps/android/2.0/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..44007d9
--- /dev/null
+++ b/gps/android/2.0/location_api/GnssAPIClient.cpp
@@ -0,0 +1,728 @@
+/* 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_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnss;
+using ::android::hardware::gnss::V2_0::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);
+
+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()
+{
+ 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();
+ }
+}
+
+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);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_0 != nullptr || gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= 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;
+
+ 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
+ }
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+
+ 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);
+ bool isTracking = mTracking;
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (flags: %02x isTracking: %d)", __FUNCTION__, location.flags, isTracking);
+
+ if (!isTracking) {
+ return;
+ }
+
+ 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);
+ mMutex.unlock();
+
+ 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);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr || gnssCbIface_2_0 != 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_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);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ 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);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ 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);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/GnssAPIClient.h b/gps/android/2.0/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..cfa78c7
--- /dev/null
+++ b/gps/android/2.0/location_api/GnssAPIClient.h
@@ -0,0 +1,115 @@
+/* Copyright (c) 2017-2019, 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.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnssCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+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 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);
+ 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;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/2.0/location_api/LocationUtil.cpp b/gps/android/2.0/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..961b7b1
--- /dev/null
+++ b/gps/android/2.0/location_api/LocationUtil.cpp
@@ -0,0 +1,334 @@
+/* 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 <gps_extended_c.h>
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+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;
+
+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;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/LocationUtil.h b/gps/android/2.0/location_api/LocationUtil.h
new file mode 100644
index 0000000..70729e4
--- /dev/null
+++ b/gps/android/2.0/location_api/LocationUtil.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2017-2019, 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 <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+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);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/2.0/location_api/MeasurementAPIClient.cpp b/gps/android/2.0/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..425415f
--- /dev/null
+++ b/gps/android/2.0/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,507 @@
+/* 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_0 {
+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 convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
+ ::android::hardware::hidl_string& 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),
+ 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;
+}
+
+// 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::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_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;
+ 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_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 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);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ }
+ 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, out.measurements[i].codeType);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
+ }
+ convertGnssClock(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);
+ }
+}
+
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
+ ::android::hardware::hidl_string& out)
+{
+ switch(in) {
+ 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;
+ default:
+ out = "UNKNOWN";
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/MeasurementAPIClient.h b/gps/android/2.0/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..6c2d38d
--- /dev/null
+++ b/gps/android/2.0/location_api/MeasurementAPIClient.h
@@ -0,0 +1,90 @@
+/* Copyright (c) 2017-2019, 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.0/IGnssMeasurement.h>
+//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+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);
+ 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;
+ bool mTracking;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/2.0/service.cpp b/gps/android/2.0/service.cpp
new file mode 100644
index 0000000..f7efb18
--- /dev/null
+++ b/gps/android/2.0/service.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@2.0-service-qti"
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V2_0::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGI("LOC_HIDL_VERSION not defined.");
+ #endif
+ joinRpcThreadpool();
+ } else {
+ ALOGE("Error while registering IGnss 2.0 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/2.1/AGnss.cpp b/gps/android/2.1/AGnss.cpp
new file mode 100644
index 0000000..c759492
--- /dev/null
+++ b/gps/android/2.1/AGnss.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
+ if (nullptr != spAGnss) {
+ spAGnss->statusCb(status.type, status.status);
+ }
+}
+
+void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {
+
+ V2_0::IAGnssCallback::AGnssType aType;
+ IAGnssCallback::AGnssStatusValue aStatus;
+
+ switch (type) {
+ case LOC_AGPS_TYPE_SUPL:
+ aType = IAGnssCallback::AGnssType::SUPL;
+ break;
+ case LOC_AGPS_TYPE_SUPL_ES:
+ aType = IAGnssCallback::AGnssType::SUPL_EIMS;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", type);
+ return;
+ }
+
+ switch (status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status);
+ return;
+ }
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ }
+ else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/AGnss.h b/gps/android/2.1/AGnss.h
new file mode 100644
index 0000000..f6ea997
--- /dev/null
+++ b/gps/android/2.1/AGnss.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+
+#include <android/hardware/gnss/2.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::hardware::gnss::V2_0::IAGnssCallback;
+
+struct Gnss;
+struct AGnss : public V2_0::IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusCb(AGpsExtType type, LocAGpsStatusValue status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<V2_0::IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
diff --git a/gps/android/2.1/AGnssRil.cpp b/gps/android/2.1/AGnssRil.cpp
new file mode 100644
index 0000000..f413e93
--- /dev/null
+++ b/gps/android/2.1/AGnssRil.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
+ ENTRY_LOG_CALLFLOW();
+ std::string apn = attributes.apn;
+ if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ bool roaming = false;
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
+ typeout = loc_core::TYPE_WIFI;
+ } else {
+ typeout = loc_core::TYPE_MOBILE;
+ }
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
+ roaming = false;
+ }
+ LOC_LOGd("apn string received is: %s", apn.c_str());
+ mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
+ typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/AGnssRil.h b/gps/android/2.1/AGnssRil.h
new file mode 100644
index 0000000..2bf6156
--- /dev/null
+++ b/gps/android/2.1/AGnssRil.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/2.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public V2_0::IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
+ Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
diff --git a/gps/android/2.1/Android.mk b/gps/android/2.1/Android.mk
new file mode 100644
index 0000000..a947e41
--- /dev/null
+++ b/gps/android/2.1/Android.mk
@@ -0,0 +1,116 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ AGnssRil.cpp \
+ GnssMeasurement.cpp \
+ GnssConfiguration.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssNi.cpp \
+ GnssDebug.cpp \
+ GnssAntennaInfo.cpp \
+ MeasurementCorrections.cpp \
+ GnssVisibilityControl.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/GnssAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/LocationUtil.cpp \
+
+ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
+LOCAL_CFLAGS += \
+ -DGNSS_HIDL_LEGACY_MEASURMENTS
+endif
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss@2.1 \
+ android.hardware.gnss.measurement_corrections@1.0 \
+ android.hardware.gnss.measurement_corrections@1.1 \
+ android.hardware.gnss.visibility_control@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.health@2.1 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.1-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@2.1-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss@2.1 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/2.1/Gnss.cpp b/gps/android/2.1/Gnss.cpp
new file mode 100644
index 0000000..37e1cc5
--- /dev/null
+++ b/gps/android/2.1/Gnss.cpp
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include "LocationUtil.h"
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
+using ::android::hardware::gnss::measurement_corrections::V1_1::
+ implementation::MeasurementCorrections;
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi != nullptr) {
+ return mApi;
+ }
+
+ if (mGnssCbIface_2_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_1);
+ } else if (mGnssCbIface_2_0 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_0);
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
+ } else if (mGnssCbIface != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ } else {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (mGnssInterface == nullptr && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+ if (NULL == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+
+ // In case where previous call to setCallback_1_1/setCallback_2_0/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssStop();
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr) {
+ mGnssMeasurement = new GnssMeasurement();
+ }
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssGeofencingIface == nullptr) {
+ mGnssGeofencingIface = new GnssGeofencing();
+ }
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssBatching == nullptr) {
+ mGnssBatching = new GnssBatching();
+ }
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_2_0/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_1_1 = callback;
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_1 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_1->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_2_0 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_1_1/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_0 = callback;
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mAGnssIface_2_0 == nullptr) {
+ mAGnssIface_2_0 = new AGnss(this);
+ }
+ return mAGnssIface_2_0;
+}
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<IMeasurementCorrectionsV1_0>>
+ Gnss::getExtensionMeasurementCorrections() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasCorr == nullptr) {
+ mGnssMeasCorr = new MeasurementCorrections(this);
+ }
+ return mGnssMeasCorr;
+}
+
+Return<sp<IMeasurementCorrectionsV1_1>>
+ Gnss::getExtensionMeasurementCorrections_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasCorr == nullptr) {
+ mGnssMeasCorr = new MeasurementCorrections(this);
+ }
+ return mGnssMeasCorr;
+}
+
+Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ Gnss::getExtensionVisibilityControl() {
+ ENTRY_LOG_CALLFLOW();
+ if (mVisibCtrl == nullptr) {
+ mVisibCtrl = new GnssVisibilityControl(this);
+ }
+ return mVisibCtrl;
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ return nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_1_1/setCallback_2_0, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_1 = callback;
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (gnssInterface != nullptr) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_1(mGnssCbIface_2_1);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr) {
+ mGnssMeasurement = new GnssMeasurement();
+ }
+ return mGnssMeasurement;
+}
+Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssAntennaInfo == nullptr) {
+ mGnssAntennaInfo = new GnssAntennaInfo(this);
+ }
+ return mGnssAntennaInfo;
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/Gnss.h b/gps/android/2.1/Gnss.h
new file mode 100644
index 0000000..c383882
--- /dev/null
+++ b/gps/android/2.1/Gnss.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssConfiguration.h>
+#include <GnssMeasurement.h>
+#include <GnssBatching.h>
+#include <GnssGeofencing.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+#include <GnssAntennaInfo.h>
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <MeasurementCorrections.h>
+#include <GnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "GnssAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using IMeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using IMeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
+using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+ Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+ Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+ Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+
+ Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<IMeasurementCorrectionsV1_0>> getExtensionMeasurementCorrections() override;
+ Return<sp<IMeasurementCorrectionsV1_1>> getExtensionMeasurementCorrections_1_1() override;
+ Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+
+ Return<bool> injectBestLocation_2_0(
+ const ::android::hardware::gnss::V2_0::GnssLocation& location) override;
+
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+ Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ getExtensionVisibilityControl() override;
+
+ // Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+ Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+ Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+ Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
+ Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<V1_0::IGnssNi> mGnssNi = nullptr;
+ sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<V1_0::IAGnss> mAGnssIface = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
+ sp<V2_0::IAGnssRil> mGnssRil = nullptr;
+ sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
+ sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssCallback> mGnssCbIface_2_1 = nullptr;
+ sp<V2_1::IGnssMeasurement> mGnssMeasurement = nullptr;
+ sp<V2_1::IGnssConfiguration> mGnssConfig = nullptr;
+ sp<V2_1::IGnssAntennaInfo> mGnssAntennaInfo = nullptr;
+ sp<IMeasurementCorrectionsV1_1> mGnssMeasCorr = nullptr;
+ sp<IGnssVisibilityControl> mVisibCtrl = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
diff --git a/gps/android/2.1/GnssAntennaInfo.cpp b/gps/android/2.1/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..62c4cc7
--- /dev/null
+++ b/gps/android/2.1/GnssAntennaInfo.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 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_TAG "LocSvc_GnssAntennaInfoInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssAntennaInfo.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static GnssAntennaInfo* spGnssAntennaInfo = nullptr;
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfos);
+
+void GnssAntennaInfo::GnssAntennaInfoDeathRecipient::serviceDied(uint64_t cookie,
+ const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+ // However, we need to inform the adapter that the service has died
+ if (nullptr == spGnssAntennaInfo) {
+ LOC_LOGE("%s]: spGnssAntennaInfo is nullptr", __FUNCTION__);
+ return;
+ }
+ if (nullptr == spGnssAntennaInfo->mGnss) {
+ LOC_LOGE("%s]: spGnssAntennaInfo->mGnss is nullptr", __FUNCTION__);
+ return;
+ }
+
+ spGnssAntennaInfo->mGnss->getGnssInterface()->antennaInfoClose();
+}
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& out) {
+
+ uint32_t vecSize, numberOfRows, numberOfColumns;
+ vecSize = in.size();
+ out.resize(vecSize);
+ for (uint32_t i = 0; i < vecSize; i++) {
+ out[i].carrierFrequencyMHz = in[i].carrierFrequencyMHz;
+ out[i].phaseCenterOffsetCoordinateMillimeters.x =
+ in[i].phaseCenterOffsetCoordinateMillimeters.x;
+ out[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty;
+ out[i].phaseCenterOffsetCoordinateMillimeters.y =
+ in[i].phaseCenterOffsetCoordinateMillimeters.y;
+ out[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty;
+ out[i].phaseCenterOffsetCoordinateMillimeters.z =
+ in[i].phaseCenterOffsetCoordinateMillimeters.z;
+ out[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty;
+
+ numberOfRows = in[i].phaseCenterVariationCorrectionMillimeters.size();
+ out[i].phaseCenterVariationCorrectionMillimeters.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].phaseCenterVariationCorrectionMillimeters[j].size();
+ out[i].phaseCenterVariationCorrectionMillimeters[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].phaseCenterVariationCorrectionMillimeters[j].row[k] =
+ in[i].phaseCenterVariationCorrectionMillimeters[j][k];
+ }
+ }
+
+ numberOfRows = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters.size();
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].size();
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].
+ row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].row[k] =
+ in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j][k];
+ }
+ }
+
+ numberOfRows = in[i].signalGainCorrectionDbi.size();
+ out[i].signalGainCorrectionDbi.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].signalGainCorrectionDbi[j].size();
+ out[i].signalGainCorrectionDbi[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].signalGainCorrectionDbi[j].row[k] = in[i].signalGainCorrectionDbi[j][k];
+ }
+ }
+
+ numberOfRows = in[i].signalGainCorrectionUncertaintyDbi.size();
+ out[i].signalGainCorrectionUncertaintyDbi.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].signalGainCorrectionUncertaintyDbi[j].size();
+ out[i].signalGainCorrectionUncertaintyDbi[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].signalGainCorrectionUncertaintyDbi[j].row[k] =
+ in[i].signalGainCorrectionUncertaintyDbi[j][k];
+ }
+ }
+ }
+}
+
+GnssAntennaInfo::GnssAntennaInfo(Gnss* gnss) : mGnss(gnss) {
+ mGnssAntennaInfoDeathRecipient = new GnssAntennaInfoDeathRecipient(this);
+ spGnssAntennaInfo = this;
+}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+ spGnssAntennaInfo = nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+Return<GnssAntennaInfo::GnssAntennaInfoStatus>
+ GnssAntennaInfo::setCallback(const sp<IGnssAntennaInfoCallback>& callback) {
+ uint32_t retValue;
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return GnssAntennaInfoStatus::ERROR_GENERIC;
+ }
+
+ mGnssAntennaInfoCbIface = callback;
+ retValue = mGnss->getGnssInterface()->antennaInfoInit(aiGnssAntennaInfoCb);
+
+ switch (retValue) {
+ case ANTENNA_INFO_SUCCESS: return GnssAntennaInfoStatus::SUCCESS;
+ case ANTENNA_INFO_ERROR_ALREADY_INIT: return GnssAntennaInfoStatus::ERROR_ALREADY_INIT;
+ case ANTENNA_INFO_ERROR_GENERIC:
+ default: return GnssAntennaInfoStatus::ERROR_GENERIC;
+ }
+}
+
+Return<void> GnssAntennaInfo::close(void) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->getGnssInterface()->antennaInfoClose();
+
+ return Void();
+}
+
+void GnssAntennaInfo::aiGnssAntennaInfoCb
+ (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+ if (nullptr != spGnssAntennaInfo) {
+ spGnssAntennaInfo->gnssAntennaInfoCb(gnssAntennaInformations);
+ }
+}
+
+void GnssAntennaInfo::gnssAntennaInfoCb
+ (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+
+ if (mGnssAntennaInfoCbIface != nullptr) {
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+
+ // Convert from one structure to another
+ convertGnssAntennaInfo(gnssAntennaInformations, antennaInfos);
+
+ auto r = mGnssAntennaInfoCbIface->gnssAntennaInfoCb(antennaInfos);
+ if (!r.isOk()) {
+ LOC_LOGw("Error antenna info cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssAntennaInfo.h b/gps/android/2.1/GnssAntennaInfo.h
new file mode 100644
index 0000000..02ddd28
--- /dev/null
+++ b/gps/android/2.1/GnssAntennaInfo.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 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 ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+
+#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssAntennaInfo : public IGnssAntennaInfo {
+ GnssAntennaInfo(Gnss* gnss);
+ ~GnssAntennaInfo();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_1::IGnssAntennaInfo follow.
+ * These declarations were generated from IGnssAntennaInfo.hal.
+ */
+ Return<GnssAntennaInfoStatus>
+ setCallback(const sp<IGnssAntennaInfoCallback>& callback) override;
+ Return<void> close(void) override;
+
+ void gnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+ static void aiGnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+ private:
+ struct GnssAntennaInfoDeathRecipient : hidl_death_recipient {
+ GnssAntennaInfoDeathRecipient(sp<GnssAntennaInfo> gnssAntennaInfo) :
+ mGnssAntennaInfo(gnssAntennaInfo) {
+ }
+ ~GnssAntennaInfoDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssAntennaInfo> mGnssAntennaInfo;
+ };
+
+ private:
+ sp<GnssAntennaInfoDeathRecipient> mGnssAntennaInfoDeathRecipient = nullptr;
+ sp<IGnssAntennaInfoCallback> mGnssAntennaInfoCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
diff --git a/gps/android/2.1/GnssBatching.cpp b/gps/android/2.1/GnssBatching.cpp
new file mode 100644
index 0000000..73e3532
--- /dev/null
+++ b/gps/android/2.1/GnssBatching.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mApi != nullptr) {
+ mApi->stopSession();
+ }
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface = nullptr;
+ }
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface_2_0 = nullptr;
+ }
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface_2_0 = callback;
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssBatching.h b/gps/android/2.1/GnssBatching.h
new file mode 100644
index 0000000..908748f
--- /dev/null
+++ b/gps/android/2.1/GnssBatching.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/Status.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::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+ Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0 = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
diff --git a/gps/android/2.1/GnssConfiguration.cpp b/gps/android/2.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..b6077ae
--- /dev/null
+++ b/gps/android/2.1/GnssConfiguration.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include "ContextBase.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using namespace loc_core;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ // deprecated function. Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ mGnss->updateConfiguration(config);
+ // Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, (GnssConstellationType)blacklist[idx].constellation,
+ blacklist[idx].svid) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+ const int16_t svid) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = svid;
+
+ switch(constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::IRNSS:
+ copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+ svIdOffset = 0;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::IRNSS:
+ copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+ svIdOffset = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnss == nullptr) {
+ LOC_LOGe("mGnss is nullptr");
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ config.emergencyExtensionSeconds = emergencyExtensionSeconds;
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist_2_1(
+ const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssConfiguration.h b/gps/android/2.1/GnssConfiguration.h
new file mode 100644
index 0000000..f000dbd
--- /dev/null
+++ b/gps/android/2.1/GnssConfiguration.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public V2_1::IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+ Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+ // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist_2_1(
+ const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+ const int16_t svid);
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
diff --git a/gps/android/2.1/GnssDebug.cpp b/gps/android/2.1/GnssDebug.cpp
new file mode 100644
index 0000000..27ff964
--- /dev/null
+++ b/gps/android/2.1/GnssDebug.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V1_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V1_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V1_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+Return<void> GnssDebug::getDebugData_2_0(getDebugData_2_0_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V2_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ }
+ else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V2_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V2_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.v1_0.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.v1_0.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.v1_0.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.v1_0.ephemerisHealth);
+
+ s.v1_0.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.v1_0.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.v1_0.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssDebug.h b/gps/android/2.1/GnssDebug.h
new file mode 100644
index 0000000..4eaf34a
--- /dev/null
+++ b/gps/android/2.1/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/2.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+ // Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow.
+ Return<void> getDebugData_2_0(getDebugData_2_0_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
diff --git a/gps/android/2.1/GnssGeofencing.cpp b/gps/android/2.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..0ca3e6d
--- /dev/null
+++ b/gps/android/2.1/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssGeofencing.h b/gps/android/2.1/GnssGeofencing.h
new file mode 100644
index 0000000..1cdca12
--- /dev/null
+++ b/gps/android/2.1/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.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::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
diff --git a/gps/android/2.1/GnssMeasurement.cpp b/gps/android/2.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..af75802
--- /dev/null
+++ b/gps/android/2.1/GnssMeasurement.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include "GnssMeasurement.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+}
+
+void GnssMeasurement::clearInterfaces() {
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ mGnssMeasurementCbIface_2_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_1 = nullptr;
+ }
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ clearInterfaces();
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_0 = callback;
+ mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_0(callback, powerMode);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
+ const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_1 = callback;
+ mGnssMeasurementCbIface_2_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_1(callback, powerMode);
+
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssMeasurement.h b/gps/android/2.1/GnssMeasurement.h
new file mode 100644
index 0000000..2ac45c6
--- /dev/null
+++ b/gps/android/2.1/GnssMeasurement.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public V2_1::IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+ // Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
+ const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1 = nullptr;
+ MeasurementAPIClient* mApi;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
diff --git a/gps/android/2.1/GnssNi.cpp b/gps/android/2.1/GnssNi.cpp
new file mode 100644
index 0000000..ba5e8d9
--- /dev/null
+++ b/gps/android/2.1/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssNi.h b/gps/android/2.1/GnssNi.h
new file mode 100644
index 0000000..9a8fb69
--- /dev/null
+++ b/gps/android/2.1/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
diff --git a/gps/android/2.1/GnssVisibilityControl.cpp b/gps/android/2.1/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..5a8c697
--- /dev/null
+++ b/gps/android/2.1/GnssVisibilityControl.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019, 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 <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "GnssVisibilityControl.h"
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+static GnssVisibilityControl* spGnssVisibilityControl = nullptr;
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out);
+
+GnssVisibilityControl::GnssVisibilityControl(Gnss* gnss) : mGnss(gnss) {
+ spGnssVisibilityControl = this;
+}
+GnssVisibilityControl::~GnssVisibilityControl() {
+ spGnssVisibilityControl = nullptr;
+}
+
+void GnssVisibilityControl::nfwStatusCb(GnssNfwNotification notification) {
+ if (nullptr != spGnssVisibilityControl) {
+ spGnssVisibilityControl->statusCb(notification);
+ }
+}
+
+bool GnssVisibilityControl::isInEmergencySession() {
+ if (nullptr != spGnssVisibilityControl) {
+ return spGnssVisibilityControl->isE911Session();
+ }
+ return false;
+}
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out)
+{
+ memset(&out, 0, sizeof(IGnssVisibilityControlCallback::NfwNotification));
+ out.proxyAppPackageName = in.proxyAppPackageName;
+ out.protocolStack = (IGnssVisibilityControlCallback::NfwProtocolStack)in.protocolStack;
+ out.otherProtocolStackName = in.otherProtocolStackName;
+ out.requestor = (IGnssVisibilityControlCallback::NfwRequestor)in.requestor;
+ out.requestorId = in.requestorId;
+ out.responseType = (IGnssVisibilityControlCallback::NfwResponseType)in.responseType;
+ out.inEmergencyMode = in.inEmergencyMode;
+ out.isCachedLocation = in.isCachedLocation;
+}
+
+void GnssVisibilityControl::statusCb(GnssNfwNotification notification) {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ IGnssVisibilityControlCallback::NfwNotification nfwNotification;
+
+ // Convert from one structure to another
+ convertGnssNfwNotification(notification, nfwNotification);
+
+ auto r = mGnssVisibilityControlCbIface->nfwNotifyCb(nfwNotification);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+bool GnssVisibilityControl::isE911Session() {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ auto r = mGnssVisibilityControlCbIface->isInEmergencySession();
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ return false;
+ } else {
+ return (r);
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ return false;
+ }
+}
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+
+ /* If the vector is empty we need to disable all NFW clients
+ If there is at least one app in the vector we need to enable
+ all NFW clients */
+ if (0 == proxyApps.size()) {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(false);
+ } else {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(true);
+ }
+
+ return true;
+}
+/**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+Return<bool> GnssVisibilityControl::setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mGnssVisibilityControlCbIface = callback;
+
+ NfwCbInfo cbInfo = {};
+ cbInfo.visibilityControlCb = (void*)nfwStatusCb;
+ cbInfo.isInEmergencySession = (void*)isInEmergencySession;
+
+ mGnss->getGnssInterface()->nfwInit(cbInfo);
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssVisibilityControl.h b/gps/android/2.1/GnssVisibilityControl.h
new file mode 100644
index 0000000..6794a64
--- /dev/null
+++ b/gps/android/2.1/GnssVisibilityControl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, 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 ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+ GnssVisibilityControl(Gnss* gnss);
+ ~GnssVisibilityControl();
+
+ // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+ Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override;
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override;
+
+ void statusCb(GnssNfwNotification notification);
+ bool isE911Session();
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void nfwStatusCb(GnssNfwNotification notification);
+ static bool isInEmergencySession();
+
+private:
+ Gnss* mGnss = nullptr;
+ sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
diff --git a/gps/android/2.1/MeasurementCorrections.cpp b/gps/android/2.1/MeasurementCorrections.cpp
new file mode 100644
index 0000000..f8f0803
--- /dev/null
+++ b/gps/android/2.1/MeasurementCorrections.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 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_TAG "LocSvc_MeasurementCorrectionsInterface"
+
+#include <log_util.h>
+#include "MeasurementCorrections.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+static MeasurementCorrections* spMeasurementCorrections = nullptr;
+
+void MeasurementCorrections::GnssMeasurementCorrectionsDeathRecipient::serviceDied(uint64_t cookie,
+ const wp<IBase>& who) {
+ LOC_LOGe("service died. cookie: %llu, who: %p", static_cast<unsigned long long>(cookie), &who);
+ // Gnss::GnssDeathrecipient will stop the session
+ // we inform the adapter that service has died
+ if (nullptr == spMeasurementCorrections) {
+ LOC_LOGe("spMeasurementCorrections is nullptr");
+ return;
+ }
+ if (nullptr == spMeasurementCorrections->mGnss ||
+ nullptr == spMeasurementCorrections->mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return;
+ }
+ spMeasurementCorrections->mGnss->getGnssInterface()->measCorrClose();
+}
+
+MeasurementCorrections::MeasurementCorrections(Gnss* gnss) : mGnss(gnss) {
+ mGnssMeasurementCorrectionsDeathRecipient = new GnssMeasurementCorrectionsDeathRecipient(this);
+ spMeasurementCorrections = this;
+}
+
+MeasurementCorrections::~MeasurementCorrections() {
+ spMeasurementCorrections = nullptr;
+}
+
+void MeasurementCorrections::measCorrSetCapabilitiesCb(
+ GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+ if (nullptr != spMeasurementCorrections) {
+ spMeasurementCorrections->setCapabilitiesCb(capabilities);
+ }
+}
+
+void MeasurementCorrections::setCapabilitiesCb(
+ GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+
+ if (mMeasurementCorrectionsCbIface != nullptr) {
+ uint32_t measCorrCapabilities = 0;
+
+ // Convert from one enum to another
+ if (capabilities & GNSS_MEAS_CORR_LOS_SATS) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::LOS_SATS;
+ }
+ if (capabilities & GNSS_MEAS_CORR_EXCESS_PATH_LENGTH) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::EXCESS_PATH_LENGTH;
+ }
+ if (capabilities & GNSS_MEAS_CORR_REFLECTING_PLANE) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::REFLECTING_PLANE;
+ }
+
+ auto r = mMeasurementCorrectionsCbIface->setCapabilitiesCb(measCorrCapabilities);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking setCapabilitiesCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<bool> MeasurementCorrections::setCorrections(
+ const MeasurementCorrectionsV1_0& corrections) {
+
+ GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+ V2_1::implementation::convertMeasurementCorrections(corrections, gnssMeasurementCorrections);
+
+ return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCorrections_1_1(
+ const MeasurementCorrectionsV1_1& corrections) {
+
+ GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+ V2_1::implementation::convertMeasurementCorrections(
+ corrections.v1_0, gnssMeasurementCorrections);
+
+ gnssMeasurementCorrections.hasEnvironmentBearing = corrections.hasEnvironmentBearing;
+ gnssMeasurementCorrections.environmentBearingDegrees =
+ corrections.environmentBearingDegrees;
+ gnssMeasurementCorrections.environmentBearingUncertaintyDegrees =
+ corrections.environmentBearingUncertaintyDegrees;
+
+ for (int i = 0; i < corrections.satCorrections.size(); i++) {
+ GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+ V2_1::implementation::convertSingleSatCorrections(
+ corrections.satCorrections[i].v1_0, gnssSingleSatCorrection);
+ switch (corrections.satCorrections[i].constellation) {
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GPS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GPS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::SBAS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_SBAS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GLONASS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GLONASS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::QZSS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_QZSS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::BEIDOU):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_BEIDOU;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GALILEO):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GALILEO;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::IRNSS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_NAVIC;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::UNKNOWN):
+ default:
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_UNKNOWN;
+ break;
+ }
+ gnssMeasurementCorrections.satCorrections.push_back(gnssSingleSatCorrection);
+ }
+
+ return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCallback(
+ const sp<V1_0::IMeasurementCorrectionsCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mMeasurementCorrectionsCbIface = callback;
+
+ return mGnss->getGnssInterface()->measCorrInit(measCorrSetCapabilitiesCb);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/MeasurementCorrections.h b/gps/android/2.1/MeasurementCorrections.h
new file mode 100644
index 0000000..92fcc6a
--- /dev/null
+++ b/gps/android/2.1/MeasurementCorrections.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 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 ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+#define ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+struct MeasurementCorrections : public V1_1::IMeasurementCorrections {
+ MeasurementCorrections(Gnss* gnss);
+ ~MeasurementCorrections();
+
+ Return<bool> setCorrections(const MeasurementCorrectionsV1_0& corrections) override;
+
+ // Methods from
+ // ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections follow.
+ Return<bool> setCorrections_1_1(const MeasurementCorrectionsV1_1& corrections);
+
+ Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
+
+ void setCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void measCorrSetCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+private:
+ struct GnssMeasurementCorrectionsDeathRecipient : hidl_death_recipient {
+ GnssMeasurementCorrectionsDeathRecipient(
+ sp<MeasurementCorrections> gnssMeasurementCorrections) :
+ mGnssMeasurementCorrections(gnssMeasurementCorrections) {
+ }
+ ~GnssMeasurementCorrectionsDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<MeasurementCorrections> mGnssMeasurementCorrections;
+ };
+ Gnss* mGnss = nullptr;
+ sp<GnssMeasurementCorrectionsDeathRecipient> mGnssMeasurementCorrectionsDeathRecipient =
+ nullptr;
+ sp<IMeasurementCorrectionsCallback> mMeasurementCorrectionsCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
diff --git a/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc
new file mode 100644
index 0000000..19e32c4
--- /dev/null
+++ b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@2.1-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml
new file mode 100755
index 0000000..842fb6e
--- /dev/null
+++ b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml
@@ -0,0 +1,36 @@
+<!-- Copyright (c) 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.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ <fqname>@2.1::IGnss/default</fqname>
+ </hal>
+</manifest>
+
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
diff --git a/gps/android/2.1/service.cpp b/gps/android/2.1/service.cpp
new file mode 100755
index 0000000..c5f040b
--- /dev/null
+++ b/gps/android/2.1/service.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@2.1-service-qti"
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V2_1::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGI("LOC_HIDL_VERSION not defined.");
+ #endif
+ joinRpcThreadpool();
+ } else {
+ ALOGE("Error while registering IGnss 2.1 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/Android.mk b/gps/android/Android.mk
new file mode 100644
index 0000000..aa2f4b5
--- /dev/null
+++ b/gps/android/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-subdir-makefiles)
diff --git a/gps/android/utils/Android.bp b/gps/android/utils/Android.bp
new file mode 100644
index 0000000..c3dc17a
--- /dev/null
+++ b/gps/android/utils/Android.bp
@@ -0,0 +1,37 @@
+cc_library_static {
+
+ name: "liblocbatterylistener",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ cflags: GNSS_CFLAGS + ["-DBATTERY_LISTENER_ENABLED"],
+ local_include_dirs: ["."],
+
+ srcs: ["battery_listener.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libcutils",
+ "libutils",
+ "android.hardware.health@1.0",
+ "android.hardware.health@2.0",
+ "android.hardware.health@2.1",
+ "android.hardware.power@1.2",
+ "libbase",
+ ],
+
+ static_libs: ["libhealthhalutils"],
+
+ header_libs: [
+ "libgps.utils_headers",
+ "libloc_pla_headers",
+ ],
+}
+
+cc_library_headers {
+
+ name: "liblocbatterylistener_headers",
+ export_include_dirs: ["."],
+}
diff --git a/gps/android/utils/battery_listener.cpp b/gps/android/utils/battery_listener.cpp
new file mode 100644
index 0000000..9cbfabd
--- /dev/null
+++ b/gps/android/utils/battery_listener.cpp
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2019-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 "battery_listener.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "LocSvc_BatteryListener"
+#define LOG_NDEBUG 0
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hardware/health/2.1/IHealth.h>
+#include <android/hardware/health/2.1/IHealthInfoCallback.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <hidl/HidlTransportSupport.h>
+#include <thread>
+#include <log_util.h>
+
+using android::hardware::interfacesEqual;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V2_1::IHealthInfoCallback;
+using android::hardware::health::V2_1::IHealth;
+using android::hardware::health::V2_0::Result;
+using android::hidl::manager::V1_0::IServiceManager;
+using namespace std::literals::chrono_literals;
+
+static bool sIsBatteryListened = false;
+namespace android {
+
+#define GET_HEALTH_SVC_RETRY_CNT 5
+#define GET_HEALTH_SVC_WAIT_TIME_MS 500
+
+struct BatteryListenerImpl : public hardware::health::V2_1::IHealthInfoCallback,
+ public hardware::hidl_death_recipient {
+ typedef std::function<void(bool)> cb_fn_t;
+ BatteryListenerImpl(cb_fn_t cb);
+ virtual ~BatteryListenerImpl ();
+ virtual hardware::Return<void> healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info);
+ virtual hardware::Return<void> healthInfoChanged_2_1(
+ const hardware::health::V2_1::HealthInfo& info);
+ virtual void serviceDied(uint64_t cookie,
+ const wp<hidl::base::V1_0::IBase>& who);
+ bool isCharging() {
+ std::lock_guard<std::mutex> _l(mLock);
+ return statusToBool(mStatus);
+ }
+ private:
+ sp<hardware::health::V2_1::IHealth> mHealth;
+ status_t init();
+ BatteryStatus mStatus;
+ cb_fn_t mCb;
+ std::mutex mLock;
+ std::condition_variable mCond;
+ std::unique_ptr<std::thread> mThread;
+ bool mDone;
+ bool statusToBool(const BatteryStatus &s) const {
+ return (s == BatteryStatus::CHARGING) ||
+ (s == BatteryStatus::FULL);
+ }
+};
+
+status_t BatteryListenerImpl::init()
+{
+ int tries = 0;
+
+ if (mHealth != NULL)
+ return INVALID_OPERATION;
+
+ do {
+ mHealth = IHealth::getService();
+ if (mHealth != NULL)
+ break;
+ usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
+ tries++;
+ } while(tries < GET_HEALTH_SVC_RETRY_CNT);
+
+ if (mHealth == NULL) {
+ LOC_LOGe("no health service found, retries %d", tries);
+ return NO_INIT;
+ } else {
+ LOC_LOGi("Get health service in %d tries", tries);
+ }
+ mStatus = BatteryStatus::UNKNOWN;
+ auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) {
+ if (r != Result::SUCCESS) {
+ LOC_LOGe("batterylistener: cannot get battery status");
+ return;
+ }
+ mStatus = status;
+ });
+ if (!ret.isOk()) {
+ LOC_LOGe("batterylistener: get charge status transaction error");
+ }
+ if (mStatus == BatteryStatus::UNKNOWN) {
+ LOC_LOGw("batterylistener: init: invalid battery status");
+ }
+ mDone = false;
+ mThread = std::make_unique<std::thread>([this]() {
+ std::unique_lock<std::mutex> l(mLock);
+ BatteryStatus local_status = mStatus;
+ while (!mDone) {
+ if (local_status == mStatus) {
+ mCond.wait(l);
+ continue;
+ }
+ local_status = mStatus;
+ switch (local_status) {
+ // NOT_CHARGING is a special event that indicates, a battery is connected,
+ // but not charging. This is seen for approx a second
+ // after charger is plugged in. A charging event is eventually received.
+ // We must try to avoid an unnecessary cb to HAL
+ // only to call it again shortly.
+ // An option to deal with this transient event would be to ignore this.
+ // Or process this event with a slight delay (i.e cancel this event
+ // if a different event comes in within a timeout
+ case BatteryStatus::NOT_CHARGING : {
+ auto mStatusnot_ncharging =
+ [this, local_status]() { return mStatus != local_status; };
+ mCond.wait_for(l, 3s, mStatusnot_ncharging);
+ if (mStatusnot_ncharging()) // i.e event changed
+ break;
+ [[clang::fallthrough]]; //explicit fall-through between switch labels
+ }
+ default:
+ bool c = statusToBool(local_status);
+ LOC_LOGi("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING");
+ l.unlock();
+ mCb(c);
+ l.lock();
+ break;
+ }
+ }
+ });
+ auto reg = mHealth->registerCallback(this);
+ if (!reg.isOk()) {
+ LOC_LOGe("Transaction error in registeringCb to HealthHAL death: %s",
+ reg.description().c_str());
+ }
+
+ auto linked = mHealth->linkToDeath(this, 0 /* cookie */);
+ if (!linked.isOk() || linked == false) {
+ LOC_LOGe("Transaction error in linking to HealthHAL death: %s",
+ linked.description().c_str());
+ }
+ return NO_ERROR;
+}
+
+BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
+ mCb(cb)
+{
+ init();
+}
+
+BatteryListenerImpl::~BatteryListenerImpl()
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth != NULL)
+ mHealth->unregisterCallback(this);
+ auto r = mHealth->unlinkToDeath(this);
+ if (!r.isOk() || r == false) {
+ LOC_LOGe("Transaction error in unregister to HealthHAL death: %s",
+ r.description().c_str());
+ }
+ }
+ mDone = true;
+ mThread->join();
+}
+
+void BatteryListenerImpl::serviceDied(uint64_t cookie __unused,
+ const wp<hidl::base::V1_0::IBase>& who)
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) {
+ LOC_LOGe("health not initialized or unknown interface died");
+ return;
+ }
+ LOC_LOGi("health service died, reinit");
+ mDone = true;
+ }
+ mHealth = NULL;
+ mCond.notify_one();
+ mThread->join();
+ std::lock_guard<std::mutex> _l(mLock);
+ init();
+}
+
+// this callback seems to be a SYNC callback and so
+// waits for return before next event is issued.
+// therefore we need not have a queue to process
+// NOT_CHARGING and CHARGING concurrencies.
+// Replace single var by a list if this assumption is broken
+Return<void> BatteryListenerImpl::healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info) {
+ LOC_LOGv("healthInfoChanged: %d", info.legacy.batteryStatus);
+ std::unique_lock<std::mutex> l(mLock);
+ if (info.legacy.batteryStatus != mStatus) {
+ mStatus = info.legacy.batteryStatus;
+ mCond.notify_one();
+ }
+ return Void();
+}
+
+Return<void> BatteryListenerImpl::healthInfoChanged_2_1(
+ const hardware::health::V2_1::HealthInfo& info) {
+ LOC_LOGv("healthInfoChanged_2_1: %d", info.legacy.legacy.batteryStatus);
+ healthInfoChanged(info.legacy);
+ return Void();
+}
+
+static sp<BatteryListenerImpl> batteryListener;
+
+bool batteryPropertiesListenerIsCharging() {
+ return batteryListener->isCharging();
+}
+
+status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb) {
+ batteryListener = new BatteryListenerImpl(cb);
+ bool isCharging = batteryPropertiesListenerIsCharging();
+ LOC_LOGv("charging status: %s charging", isCharging ? "" : "not");;
+ if (isCharging) {
+ cb(isCharging);
+ }
+ return NO_ERROR;
+}
+
+status_t batteryPropertiesListenerDeinit() {
+ batteryListener.clear();
+ return OK;
+}
+
+} // namespace android
+
+void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) {
+ LOC_LOGv("loc_extn_battery_properties_listener_init entry");
+ if (!sIsBatteryListened) {
+ std::thread t1(android::batteryPropertiesListenerInit,
+ [=](bool charging) { fn(charging); });
+ t1.detach();
+ sIsBatteryListened = true;
+ }
+}
+
+void loc_extn_battery_properties_listener_deinit() {
+ android::batteryPropertiesListenerDeinit();
+}
+
+bool loc_extn_battery_properties_is_charging() {
+ return android::batteryPropertiesListenerIsCharging();
+}
diff --git a/gps/android/utils/battery_listener.h b/gps/android/utils/battery_listener.h
new file mode 100644
index 0000000..bb6b715
--- /dev/null
+++ b/gps/android/utils/battery_listener.h
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2019, 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.
+*/
+typedef void (* battery_status_change_fn_t)(bool);
+void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn);
+void loc_extn_battery_properties_listener_deinit();
+bool loc_extn_battery_properties_is_charging();