summaryrefslogtreecommitdiffstats
path: root/gnss
diff options
context:
space:
mode:
Diffstat (limited to 'gnss')
-rw-r--r--gnss/1.0/AGnss.cpp198
-rw-r--r--gnss/1.0/AGnss.h85
-rw-r--r--gnss/1.0/AGnssRil.cpp152
-rw-r--r--gnss/1.0/AGnssRil.h88
-rw-r--r--gnss/1.0/Android.bp54
-rw-r--r--gnss/1.0/Gnss.cpp761
-rw-r--r--gnss/1.0/Gnss.h185
-rw-r--r--gnss/1.0/GnssBatching.cpp225
-rw-r--r--gnss/1.0/GnssBatching.h67
-rw-r--r--gnss/1.0/GnssConfiguration.cpp117
-rw-r--r--gnss/1.0/GnssConfiguration.h66
-rw-r--r--gnss/1.0/GnssDebug.cpp59
-rw-r--r--gnss/1.0/GnssDebug.h62
-rw-r--r--gnss/1.0/GnssGeofencing.cpp225
-rw-r--r--gnss/1.0/GnssGeofencing.h97
-rw-r--r--gnss/1.0/GnssMeasurement.cpp260
-rw-r--r--gnss/1.0/GnssMeasurement.h84
-rw-r--r--gnss/1.0/GnssNavigationMessage.cpp95
-rw-r--r--gnss/1.0/GnssNavigationMessage.h77
-rw-r--r--gnss/1.0/GnssNi.cpp109
-rw-r--r--gnss/1.0/GnssNi.h81
-rw-r--r--gnss/1.0/GnssUtils.cpp93
-rw-r--r--gnss/1.0/GnssUtils.h47
-rw-r--r--gnss/1.0/GnssXtra.cpp95
-rw-r--r--gnss/1.0/GnssXtra.h80
-rw-r--r--gnss/1.0/OWNERS3
-rw-r--r--gnss/1.0/ThreadCreationWrapper.cpp42
-rw-r--r--gnss/1.0/ThreadCreationWrapper.h58
-rw-r--r--gnss/1.0/android.hardware.gnss@1.0-service.rc4
-rw-r--r--gnss/1.0/service.cpp17
30 files changed, 3586 insertions, 0 deletions
diff --git a/gnss/1.0/AGnss.cpp b/gnss/1.0/AGnss.cpp
new file mode 100644
index 0000000..29c6ddd
--- /dev/null
+++ b/gnss/1.0/AGnss.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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_AGnssInterface"
+
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
+sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
+bool AGnss::sInterfaceExists = false;
+
+AGpsCallbacks AGnss::sAGnssCb = {
+ .status_cb = statusCb,
+ .create_thread_cb = createThreadCb
+};
+
+AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+}
+
+AGnss::~AGnss() {
+ sThreadFuncArgsList.clear();
+ sInterfaceExists = false;
+}
+
+void AGnss::statusCb(AGpsStatus* status) {
+ if (sAGnssCbIface == nullptr) {
+ ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (status == nullptr) {
+ ALOGE("AGNSS status is invalid");
+ return;
+ }
+
+ /*
+ * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
+ * AGpsStatus is checked for backward compatibility since some devices may
+ * be sending out an older version of AGpsStatus that only supports IPv4.
+ */
+ size_t statusSize = status->size;
+ if (status->size == sizeof(AGpsStatus)) {
+ switch (status->addr.ss_family)
+ {
+ case AF_INET:
+ {
+ /*
+ * ss_family indicates IPv4.
+ */
+ struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
+ IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+ .type = static_cast<IAGnssCallback::AGnssType>(status->type),
+ .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+ .ipV4Addr = in->sin_addr.s_addr,
+ };
+
+ /*
+ * Callback to client with agnssStatusIpV4Cb.
+ */
+ auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+ break;
+ }
+ case AF_INET6:
+ {
+ /*
+ * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
+ */
+ IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
+
+ aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
+ aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
+ status->status);
+
+ struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
+ &(status->addr));
+ memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
+ aGnssStatusIpV6.ipV6Addr.size());
+ auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+ break;
+ }
+ default:
+ ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
+ }
+ } else if (statusSize >= sizeof(AGpsStatus_v2)) {
+ AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
+ uint32_t ipV4Addr = statusV2->ipaddr;
+ IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+ .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
+ .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+ /*
+ * For older versions of AGpsStatus, change IP addr to net order. This
+ * was earlier being done in GnssLocationProvider.
+ */
+ .ipV4Addr = htonl(ipV4Addr)
+ };
+ /*
+ * Callback to client with agnssStatusIpV4Cb.
+ */
+ auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+ } else {
+ ALOGE("%s: Invalid size for AGPS Status", __func__);
+ }
+}
+
+pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+/*
+ * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
+ */
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+ if (mAGnssIface == nullptr) {
+ ALOGE("%s: AGnss interface is unavailable", __func__);
+ return Void();
+ }
+
+ sAGnssCbIface = callback;
+
+ mAGnssIface->init(&sAGnssCb);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+ if (mAGnssIface == nullptr) {
+ ALOGE("%s: AGnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mAGnssIface->data_conn_closed() == 0);
+}
+
+Return<bool> AGnss::dataConnFailed() {
+ if (mAGnssIface == nullptr) {
+ ALOGE("%s: AGnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mAGnssIface->data_conn_failed() == 0);
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mAGnssIface == nullptr) {
+ ALOGE("%s: AGnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
+ if (mAGnssIface == nullptr) {
+ ALOGE("%s: AGnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
+ static_cast<uint16_t>(apnIpType)) == 0);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/AGnss.h b/gnss/1.0/AGnss.h
new file mode 100644
index 0000000..2a8eed0
--- /dev/null
+++ b/gnss/1.0/AGnss.h
@@ -0,0 +1,85 @@
+/*
+ * 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 <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hardware/gps_internal.h>
+#include <hidl/Status.h>
+#include <netinet/in.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;
+
+/*
+ * Extended interface for AGNSS support. Also contains wrapper methods to allow
+ * methods from IAGnssCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct AGnss : public IAGnss {
+ AGnss(const AGpsInterface* agpsIface);
+ ~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> setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+ Return<bool> dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) override;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default
+ * implementation. These methods are not part of the IAGnss base class.
+ */
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+ static void statusCb(AGpsStatus* status);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static AGpsCallbacks sAGnssCb;
+
+ private:
+ const AGpsInterface* mAGnssIface = nullptr;
+ static sp<IAGnssCallback> sAGnssCbIface;
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static bool sInterfaceExists;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_AGnss_H_
diff --git a/gnss/1.0/AGnssRil.cpp b/gnss/1.0/AGnssRil.cpp
new file mode 100644
index 0000000..1458327
--- /dev/null
+++ b/gnss/1.0/AGnssRil.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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_AGnssRilInterface"
+
+#include "AGnssRil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnssRil::sThreadFuncArgsList;
+sp<IAGnssRilCallback> AGnssRil::sAGnssRilCbIface = nullptr;
+bool AGnssRil::sInterfaceExists = false;
+
+AGpsRilCallbacks AGnssRil::sAGnssRilCb = {
+ .request_setid = AGnssRil::requestSetId,
+ .request_refloc = AGnssRil::requestRefLoc,
+ .create_thread_cb = AGnssRil::createThreadCb
+};
+
+AGnssRil::AGnssRil(const AGpsRilInterface* aGpsRilIface) : mAGnssRilIface(aGpsRilIface) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+}
+
+AGnssRil::~AGnssRil() {
+ sThreadFuncArgsList.clear();
+ sInterfaceExists = false;
+}
+
+void AGnssRil::requestSetId(uint32_t flags) {
+ if (sAGnssRilCbIface == nullptr) {
+ ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = sAGnssRilCbIface->requestSetIdCb(flags);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void AGnssRil::requestRefLoc(uint32_t /*flags*/) {
+ if (sAGnssRilCbIface == nullptr) {
+ ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = sAGnssRilCbIface->requestRefLocCb();
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+pthread_t AGnssRil::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+Return<void> AGnssRil::setCallback(const sp<IAGnssRilCallback>& callback) {
+ if (mAGnssRilIface == nullptr) {
+ ALOGE("%s: AGnssRil interface is unavailable", __func__);
+ return Void();
+ }
+
+ sAGnssRilCbIface = callback;
+
+ mAGnssRilIface->init(&sAGnssRilCb);
+ return Void();
+}
+
+Return<void> AGnssRil::setRefLocation(const IAGnssRil::AGnssRefLocation& aGnssRefLocation) {
+ if (mAGnssRilIface == nullptr) {
+ ALOGE("%s: AGnssRil interface is unavailable", __func__);
+ return Void();
+ }
+
+ AGpsRefLocation aGnssRefloc;
+ aGnssRefloc.type = static_cast<uint16_t>(aGnssRefLocation.type);
+
+ auto& cellID = aGnssRefLocation.cellID;
+ aGnssRefloc.u.cellID = {
+ .type = static_cast<uint16_t>(cellID.type),
+ .mcc = cellID.mcc,
+ .mnc = cellID.mnc,
+ .lac = cellID.lac,
+ .cid = cellID.cid,
+ .tac = cellID.tac,
+ .pcid = cellID.pcid
+ };
+
+ mAGnssRilIface->set_ref_location(&aGnssRefloc, sizeof(aGnssRefloc));
+ return Void();
+}
+
+Return<bool> AGnssRil::setSetId(IAGnssRil::SetIDType type, const hidl_string& setid) {
+ if (mAGnssRilIface == nullptr) {
+ ALOGE("%s: AGnssRil interface is unavailable", __func__);
+ return false;
+ }
+
+ mAGnssRilIface->set_set_id(static_cast<uint16_t>(type), setid.c_str());
+ return true;
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected,
+ IAGnssRil::NetworkType type,
+ bool roaming) {
+ if (mAGnssRilIface == nullptr) {
+ ALOGE("%s: AGnssRil interface is unavailable", __func__);
+ return false;
+ }
+
+ mAGnssRilIface->update_network_state(connected,
+ static_cast<int>(type),
+ roaming,
+ nullptr /* extra_info */);
+ return true;
+}
+
+Return<bool> AGnssRil::updateNetworkAvailability(bool available, const hidl_string& apn) {
+ if (mAGnssRilIface == nullptr) {
+ ALOGE("%s: AGnssRil interface is unavailable", __func__);
+ return false;
+ }
+
+ mAGnssRilIface->update_network_availability(available, apn.c_str());
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/AGnssRil.h b/gnss/1.0/AGnssRil.h
new file mode 100644
index 0000000..6215a9e
--- /dev/null
+++ b/gnss/1.0/AGnssRil.h
@@ -0,0 +1,88 @@
+/*
+ * 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 <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hardware/gps.h>
+#include <hidl/Status.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;
+
+/*
+ * 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(const AGpsRilInterface* aGpsRilIface);
+ ~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> setRefLocation(const IAGnssRil::AGnssRefLocation& agnssReflocation) override;
+ Return<bool> setSetId(IAGnssRil::SetIDType type, const hidl_string& setid) override;
+ Return<bool> updateNetworkState(bool connected,
+ IAGnssRil::NetworkType type,
+ bool roaming) override;
+ Return<bool> updateNetworkAvailability(bool available, const hidl_string& apn) override;
+ static void requestSetId(uint32_t flags);
+ static void requestRefLoc(uint32_t flags);
+
+ /*
+ * Callback method to be passed into the conventional GNSS HAL by the default
+ * implementation. This method is not part of the IAGnssRil base class.
+ */
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static AGpsRilCallbacks sAGnssRilCb;
+
+ private:
+ const AGpsRilInterface* mAGnssRilIface = nullptr;
+ static sp<IAGnssRilCallback> sAGnssRilCbIface;
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static bool sInterfaceExists;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_AGnssRil_H_
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
new file mode 100644
index 0000000..ca495e6
--- /dev/null
+++ b/gnss/1.0/Android.bp
@@ -0,0 +1,54 @@
+cc_library_shared {
+ name: "android.hardware.gnss@1.0-impl",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "ThreadCreationWrapper.cpp",
+ "AGnss.cpp",
+ "AGnssRil.cpp",
+ "Gnss.cpp",
+ "GnssBatching.cpp",
+ "GnssDebug.cpp",
+ "GnssGeofencing.cpp",
+ "GnssMeasurement.cpp",
+ "GnssNavigationMessage.cpp",
+ "GnssNi.cpp",
+ "GnssXtra.cpp",
+ "GnssConfiguration.cpp",
+ "GnssUtils.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "android.hardware.gnss@1.0",
+ "libhardware",
+ ],
+
+}
+
+cc_binary {
+ relative_install_path: "hw",
+ vendor: true,
+ name: "android.hardware.gnss@1.0-service",
+ defaults: ["hidl_defaults"],
+ init_rc: ["android.hardware.gnss@1.0-service.rc"],
+ srcs: ["service.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libdl",
+ "libbase",
+ "libutils",
+ "libhardware",
+ "libbinder",
+ "libhidlbase",
+ "libhidltransport",
+ "android.hardware.gnss@1.0",
+ ],
+
+}
diff --git a/gnss/1.0/Gnss.cpp b/gnss/1.0/Gnss.cpp
new file mode 100644
index 0000000..32c131c
--- /dev/null
+++ b/gnss/1.0/Gnss.cpp
@@ -0,0 +1,761 @@
+/*
+ * 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_GnssInterface"
+
+#include "Gnss.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
+sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
+bool Gnss::sInterfaceExists = false;
+bool Gnss::sWakelockHeldGnss = false;
+bool Gnss::sWakelockHeldFused = false;
+
+GpsCallbacks Gnss::sGnssCb = {
+ .size = sizeof(GpsCallbacks),
+ .location_cb = locationCb,
+ .status_cb = statusCb,
+ .sv_status_cb = gpsSvStatusCb,
+ .nmea_cb = nmeaCb,
+ .set_capabilities_cb = setCapabilitiesCb,
+ .acquire_wakelock_cb = acquireWakelockCb,
+ .release_wakelock_cb = releaseWakelockCb,
+ .create_thread_cb = createThreadCb,
+ .request_utc_time_cb = requestUtcTimeCb,
+ .set_system_info_cb = setSystemInfoCb,
+ .gnss_sv_status_cb = gnssSvStatusCb,
+};
+
+uint32_t Gnss::sCapabilitiesCached = 0;
+uint16_t Gnss::sYearOfHwCached = 0;
+
+Gnss::Gnss(gps_device_t* gnssDevice) :
+ mDeathRecipient(new GnssHidlDeathRecipient(this)) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+
+ if (gnssDevice == nullptr) {
+ ALOGE("%s: Invalid device_t handle", __func__);
+ return;
+ }
+
+ mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
+}
+
+Gnss::~Gnss() {
+ sInterfaceExists = false;
+ sThreadFuncArgsList.clear();
+}
+
+void Gnss::locationCb(GpsLocation* location) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (location == nullptr) {
+ ALOGE("%s: Invalid location from GNSS HAL", __func__);
+ return;
+ }
+
+ android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
+ auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void Gnss::statusCb(GpsStatus* gnssStatus) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (gnssStatus == nullptr) {
+ ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
+ return;
+ }
+
+ IGnssCallback::GnssStatusValue status =
+ static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
+
+ auto ret = sGnssCbIface->gnssStatusCb(status);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void Gnss::gnssSvStatusCb(GnssSvStatus* status) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (status == nullptr) {
+ ALOGE("Invalid status from GNSS HAL %s", __func__);
+ return;
+ }
+
+ IGnssCallback::GnssSvStatus svStatus;
+ svStatus.numSvs = status->num_svs;
+
+ if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
+ ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+ svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
+ }
+
+ for (size_t i = 0; i < svStatus.numSvs; i++) {
+ auto svInfo = status->gnss_sv_list[i];
+ IGnssCallback::GnssSvInfo gnssSvInfo = {
+ .svid = svInfo.svid,
+ .constellation = static_cast<
+ android::hardware::gnss::V1_0::GnssConstellationType>(
+ svInfo.constellation),
+ .cN0Dbhz = svInfo.c_n0_dbhz,
+ .elevationDegrees = svInfo.elevation,
+ .azimuthDegrees = svInfo.azimuth,
+ // Older chipsets do not provide carrier frequency, hence
+ // HAS_CARRIER_FREQUENCY flag and the carrierFrequencyHz fields
+ // are not set. So we are resetting both fields here.
+ .svFlag = static_cast<uint8_t>(
+ svInfo.flags &= ~(static_cast<uint8_t>(
+ IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY))),
+ .carrierFrequencyHz = 0};
+ svStatus.gnssSvList[i] = gnssSvInfo;
+ }
+
+ auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+/*
+ * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
+ * to GnssSvStatus for backward compatibility. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum SvidValues : uint16_t {
+ GLONASS_SVID_OFFSET = 64,
+ GLONASS_SVID_COUNT = 24,
+ BEIDOU_SVID_OFFSET = 200,
+ BEIDOU_SVID_COUNT = 35,
+ SBAS_SVID_MIN = 33,
+ SBAS_SVID_MAX = 64,
+ SBAS_SVID_ADD = 87,
+ QZSS_SVID_MIN = 193,
+ QZSS_SVID_MAX = 200
+};
+
+/*
+ * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
+ * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
+ * being deprecated and is no longer part of the GNSS interface.
+ */
+void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (svInfo == nullptr) {
+ ALOGE("Invalid status from GNSS HAL %s", __func__);
+ return;
+ }
+
+ IGnssCallback::GnssSvStatus svStatus;
+ svStatus.numSvs = svInfo->num_svs;
+ /*
+ * Clamp the list size since GnssSvStatus can support a maximum of
+ * GnssMax::SVS_COUNT entries.
+ */
+ if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
+ ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+ svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
+ }
+
+ uint32_t ephemerisMask = svInfo->ephemeris_mask;
+ uint32_t almanacMask = svInfo->almanac_mask;
+ uint32_t usedInFixMask = svInfo->used_in_fix_mask;
+ /*
+ * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
+ */
+ for (size_t i = 0; i < svStatus.numSvs; i++) {
+ IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
+ info.svid = svInfo->sv_list[i].prn;
+ if (info.svid >= 1 && info.svid <= 32) {
+ info.constellation = GnssConstellationType::GPS;
+ } else if (info.svid > GLONASS_SVID_OFFSET &&
+ info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
+ info.constellation = GnssConstellationType::GLONASS;
+ info.svid -= GLONASS_SVID_OFFSET;
+ } else if (info.svid > BEIDOU_SVID_OFFSET &&
+ info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
+ info.constellation = GnssConstellationType::BEIDOU;
+ info.svid -= BEIDOU_SVID_OFFSET;
+ } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
+ info.constellation = GnssConstellationType::SBAS;
+ info.svid += SBAS_SVID_ADD;
+ } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
+ info.constellation = GnssConstellationType::QZSS;
+ } else {
+ ALOGD("Unknown constellation type with Svid = %d.", info.svid);
+ info.constellation = GnssConstellationType::UNKNOWN;
+ }
+
+ info.cN0Dbhz = svInfo->sv_list[i].snr;
+ info.elevationDegrees = svInfo->sv_list[i].elevation;
+ info.azimuthDegrees = svInfo->sv_list[i].azimuth;
+ // TODO: b/31702236
+ info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+
+ /*
+ * Only GPS info is valid for these fields, as these masks are just 32
+ * bits, by GPS prn.
+ */
+ if (info.constellation == GnssConstellationType::GPS) {
+ int32_t svidMask = (1 << (info.svid - 1));
+ if ((ephemerisMask & svidMask) != 0) {
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ }
+ if ((almanacMask & svidMask) != 0) {
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ }
+ if ((usedInFixMask & svidMask) != 0) {
+ info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ }
+ }
+ }
+
+ auto ret = sGnssCbIface->gnssSvStatusCb(svStatus);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(nmea, length);
+ auto ret = sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void Gnss::setCapabilitiesCb(uint32_t capabilities) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = sGnssCbIface->gnssSetCapabilitesCb(capabilities);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+
+ // Save for reconnection when some legacy hal's don't resend this info
+ sCapabilitiesCached = capabilities;
+}
+
+void Gnss::acquireWakelockCb() {
+ acquireWakelockGnss();
+}
+
+void Gnss::releaseWakelockCb() {
+ releaseWakelockGnss();
+}
+
+
+void Gnss::acquireWakelockGnss() {
+ sWakelockHeldGnss = true;
+ updateWakelock();
+}
+
+void Gnss::releaseWakelockGnss() {
+ sWakelockHeldGnss = false;
+ updateWakelock();
+}
+
+void Gnss::acquireWakelockFused() {
+ sWakelockHeldFused = true;
+ updateWakelock();
+}
+
+void Gnss::releaseWakelockFused() {
+ sWakelockHeldFused = false;
+ updateWakelock();
+}
+
+void Gnss::updateWakelock() {
+ // Track the state of the last request - in case the wake lock in the layer above is reference
+ // counted.
+ static bool sWakelockHeld = false;
+
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (sWakelockHeldGnss || sWakelockHeldFused) {
+ if (!sWakelockHeld) {
+ ALOGI("%s: GNSS HAL Wakelock acquired due to gps: %d, fused: %d", __func__,
+ sWakelockHeldGnss, sWakelockHeldFused);
+ sWakelockHeld = true;
+ auto ret = sGnssCbIface->gnssAcquireWakelockCb();
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+ }
+ } else {
+ if (sWakelockHeld) {
+ ALOGI("%s: GNSS HAL Wakelock released", __func__);
+ } else {
+ // To avoid burning power, always release, even if logic got here with sWakelock false
+ // which it shouldn't, unless underlying *.h implementation makes duplicate requests.
+ ALOGW("%s: GNSS HAL Wakelock released, duplicate request", __func__);
+ }
+ sWakelockHeld = false;
+ auto ret = sGnssCbIface->gnssReleaseWakelockCb();
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+ }
+}
+
+void Gnss::requestUtcTimeCb() {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = sGnssCbIface->gnssRequestTimeCb();
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
+ if (sGnssCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (info == nullptr) {
+ ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
+ return;
+ }
+
+ IGnssCallback::GnssSystemInfo gnssInfo = {
+ .yearOfHw = info->year_of_hw
+ };
+
+ auto ret = sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+
+ // Save for reconnection when some legacy hal's don't resend this info
+ sYearOfHwCached = info->year_of_hw;
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ if (callback == nullptr) {
+ ALOGE("%s: Null callback ignored", __func__);
+ return false;
+ }
+
+ if (sGnssCbIface != NULL) {
+ ALOGW("%s called more than once. Unexpected unless test.", __func__);
+ sGnssCbIface->unlinkToDeath(mDeathRecipient);
+ }
+
+ sGnssCbIface = callback;
+ callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+
+ // If this was received in the past, send it up again to refresh caller.
+ // mGnssIface will override after init() is called below, if needed
+ // (though it's unlikely the gps.h capabilities or system info will change.)
+ if (sCapabilitiesCached != 0) {
+ setCapabilitiesCb(sCapabilitiesCached);
+ }
+ if (sYearOfHwCached != 0) {
+ LegacyGnssSystemInfo info;
+ info.year_of_hw = sYearOfHwCached;
+ setSystemInfoCb(&info);
+ }
+
+ return (mGnssIface->init(&sGnssCb) == 0);
+}
+
+Return<bool> Gnss::start() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mGnssIface->start() == 0);
+}
+
+Return<bool> Gnss::stop() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mGnssIface->stop() == 0);
+}
+
+Return<void> Gnss::cleanup() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ } else {
+ mGnssIface->cleanup();
+ }
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
+}
+
+Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags) {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ } else {
+ mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
+ static_cast<GpsPositionRecurrence>(recurrence),
+ minIntervalMs,
+ preferredAccuracyMeters,
+ preferredTimeMs) == 0);
+}
+
+Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssRil == nullptr) {
+ const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
+ mGnssIface->get_extension(AGPS_RIL_INTERFACE));
+ if (agpsRilIface == nullptr) {
+ ALOGI("%s: GnssRil interface not implemented by HAL", __func__);
+ } else {
+ mGnssRil = new AGnssRil(agpsRilIface);
+ }
+ }
+ return mGnssRil;
+}
+
+Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssConfig == nullptr) {
+ const GnssConfigurationInterface* gnssConfigIface =
+ static_cast<const GnssConfigurationInterface*>(
+ mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
+
+ if (gnssConfigIface == nullptr) {
+ ALOGE("%s: GnssConfiguration interface not implemented by HAL", __func__);
+ } else {
+ mGnssConfig = new GnssConfiguration(gnssConfigIface);
+ }
+ }
+ return mGnssConfig;
+}
+
+Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssGeofencingIface == nullptr) {
+ const GpsGeofencingInterface* gpsGeofencingIface =
+ static_cast<const GpsGeofencingInterface*>(
+ mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
+
+ if (gpsGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface not implemented by HAL", __func__);
+ } else {
+ mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
+ }
+ }
+
+ return mGnssGeofencingIface;
+}
+
+Return<sp<IAGnss>> Gnss::getExtensionAGnss() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mAGnssIface == nullptr) {
+ const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
+ mGnssIface->get_extension(AGPS_INTERFACE));
+ if (agpsIface == nullptr) {
+ ALOGE("%s: AGnss interface not implemented by HAL", __func__);
+ } else {
+ mAGnssIface = new AGnss(agpsIface);
+ }
+ }
+ return mAGnssIface;
+}
+
+Return<sp<IGnssNi>> Gnss::getExtensionGnssNi() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssNi == nullptr) {
+ const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
+ mGnssIface->get_extension(GPS_NI_INTERFACE));
+ if (gpsNiIface == nullptr) {
+ ALOGI("%s: GnssNi interface not implemented by HAL", __func__);
+ } else {
+ mGnssNi = new GnssNi(gpsNiIface);
+ }
+ }
+ return mGnssNi;
+}
+
+Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssMeasurement == nullptr) {
+ const GpsMeasurementInterface* gpsMeasurementIface =
+ static_cast<const GpsMeasurementInterface*>(
+ mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
+
+ if (gpsMeasurementIface == nullptr) {
+ ALOGE("%s: GnssMeasurement interface not implemented by HAL", __func__);
+ } else {
+ mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
+ }
+ }
+ return mGnssMeasurement;
+}
+
+Return<sp<IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssNavigationMessage == nullptr) {
+ const GpsNavigationMessageInterface* gpsNavigationMessageIface =
+ static_cast<const GpsNavigationMessageInterface*>(
+ mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
+
+ if (gpsNavigationMessageIface == nullptr) {
+ ALOGI("%s: GnssNavigationMessage interface not implemented by HAL", __func__);
+ } else {
+ mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
+ }
+ }
+
+ return mGnssNavigationMessage;
+}
+
+Return<sp<IGnssXtra>> Gnss::getExtensionXtra() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssXtraIface == nullptr) {
+ const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
+ mGnssIface->get_extension(GPS_XTRA_INTERFACE));
+
+ if (gpsXtraIface == nullptr) {
+ ALOGI("%s: GnssXtra interface not implemented by HAL", __func__);
+ } else {
+ mGnssXtraIface = new GnssXtra(gpsXtraIface);
+ }
+ }
+
+ return mGnssXtraIface;
+}
+
+Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssDebug == nullptr) {
+ const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
+ mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
+
+ if (gpsDebugIface == nullptr) {
+ ALOGI("%s: GnssDebug interface not implemented by HAL", __func__);
+ } else {
+ mGnssDebug = new GnssDebug(gpsDebugIface);
+ }
+ }
+
+ return mGnssDebug;
+}
+
+Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ if (mGnssIface == nullptr) {
+ ALOGE("%s: Gnss interface is unavailable", __func__);
+ return nullptr;
+ }
+
+ if (mGnssBatching == nullptr) {
+ hw_module_t* module;
+ const FlpLocationInterface* flpLocationIface = nullptr;
+ int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+ if (err != 0) {
+ ALOGE("gnss flp hw_get_module failed: %d", err);
+ } else if (module == nullptr) {
+ ALOGE("Fused Location hw_get_module returned null module");
+ } else if (module->methods == nullptr) {
+ ALOGE("Fused Location hw_get_module returned null methods");
+ } else {
+ hw_device_t* device;
+ err = module->methods->open(module, FUSED_LOCATION_HARDWARE_MODULE_ID, &device);
+ if (err != 0) {
+ ALOGE("flpDevice open failed: %d", err);
+ } else {
+ flp_device_t * flpDevice = reinterpret_cast<flp_device_t*>(device);
+ flpLocationIface = flpDevice->get_flp_interface(flpDevice);
+ }
+ }
+
+ if (flpLocationIface == nullptr) {
+ ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
+ } else {
+ mGnssBatching = new GnssBatching(flpLocationIface);
+ }
+ }
+ return mGnssBatching;
+}
+
+void Gnss::handleHidlDeath() {
+ ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+ // commands down to the HAL implementation
+ stop(); // stop ongoing GPS tracking
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+ if (mGnssNavigationMessage != nullptr) {
+ mGnssNavigationMessage->close();
+ }
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+ cleanup();
+
+ /*
+ * This has died, so close it off in case (race condition) callbacks happen
+ * before HAL processes above messages.
+ */
+ sGnssCbIface = nullptr;
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
+ hw_module_t* module;
+ IGnss* iface = nullptr;
+ int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+ if (err == 0) {
+ hw_device_t* device;
+ err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
+ if (err == 0) {
+ iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
+ } else {
+ ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+ }
+ } else {
+ ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/Gnss.h b/gnss/1.0/Gnss.h
new file mode 100644
index 0000000..faf903c
--- /dev/null
+++ b/gnss/1.0/Gnss.h
@@ -0,0 +1,185 @@
+/*
+ * 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 <GnssDebug.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNavigationMessage.h>
+#include <GnssNi.h>
+#include <GnssXtra.h>
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssSystemInfo = ::GnssSystemInfo;
+
+/*
+ * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
+ * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+class Gnss : public IGnss {
+ public:
+ Gnss(gps_device_t* gnss_device);
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<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(IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<IAGnssRil>> getExtensionAGnssRil() override;
+ Return<sp<IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<IAGnss>> getExtensionAGnss() override;
+ Return<sp<IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+ Return<sp<IGnssXtra>> getExtensionXtra() override;
+ Return<sp<IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<IGnssDebug>> getExtensionGnssDebug() override;
+ Return<sp<IGnssBatching>> getExtensionGnssBatching() override;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default
+ * implementation. These methods are not part of the IGnss base class.
+ */
+ static void locationCb(GpsLocation* location);
+ static void statusCb(GpsStatus* gnss_status);
+ static void nmeaCb(GpsUtcTime timestamp, const char* nmea, int length);
+ static void setCapabilitiesCb(uint32_t capabilities);
+ static void acquireWakelockCb();
+ static void releaseWakelockCb();
+ static void requestUtcTimeCb();
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+ static void gnssSvStatusCb(GnssSvStatus* status);
+ /*
+ * Deprecated callback added for backward compatibility to devices that do
+ * not support GnssSvStatus.
+ */
+ static void gpsSvStatusCb(GpsSvStatus* status);
+ static void setSystemInfoCb(const LegacyGnssSystemInfo* info);
+
+ /*
+ * Wakelock consolidation, only needed for dual use of a gps.h & fused_location.h HAL
+ *
+ * Ensures that if the last call from either legacy .h was to acquire a wakelock, that a
+ * wakelock is held. Otherwise releases it.
+ */
+ static void acquireWakelockFused();
+ static void releaseWakelockFused();
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsCallbacks sGnssCb;
+
+ private:
+ /*
+ * For handling system-server death while GNSS service lives on.
+ */
+ class GnssHidlDeathRecipient : public hidl_death_recipient {
+ public:
+ GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
+ }
+
+ virtual void serviceDied(uint64_t /*cookie*/,
+ const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ mGnss->handleHidlDeath();
+ }
+ private:
+ sp<Gnss> mGnss;
+ };
+
+ // for wakelock consolidation, see above
+ static void acquireWakelockGnss();
+ static void releaseWakelockGnss();
+ static void updateWakelock();
+ static bool sWakelockHeldGnss;
+ static bool sWakelockHeldFused;
+
+ /*
+ * Cleanup for death notification
+ */
+ void handleHidlDeath();
+
+ sp<GnssXtra> mGnssXtraIface = nullptr;
+ sp<AGnssRil> mGnssRil = nullptr;
+ sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<AGnss> mAGnssIface = nullptr;
+ sp<GnssNi> mGnssNi = nullptr;
+ sp<GnssMeasurement> mGnssMeasurement = nullptr;
+ sp<GnssNavigationMessage> mGnssNavigationMessage = nullptr;
+ sp<GnssDebug> mGnssDebug = nullptr;
+ sp<GnssConfiguration> mGnssConfig = nullptr;
+ sp<GnssBatching> mGnssBatching = nullptr;
+
+ sp<GnssHidlDeathRecipient> mDeathRecipient;
+
+ const GpsInterface* mGnssIface = nullptr;
+ static sp<IGnssCallback> sGnssCbIface;
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static bool sInterfaceExists;
+
+ // Values saved for resend
+ static uint32_t sCapabilitiesCached;
+ static uint16_t sYearOfHwCached;
+};
+
+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/gnss/1.0/GnssBatching.cpp b/gnss/1.0/GnssBatching.cpp
new file mode 100644
index 0000000..f2e2e45
--- /dev/null
+++ b/gnss/1.0/GnssBatching.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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_GnssBatchingInterface"
+
+#include "GnssBatching.h"
+#include <Gnss.h> // for wakelock consolidation
+#include <GnssUtils.h>
+
+#include <android/log.h> // for ALOGE
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssBatchingCallback> GnssBatching::sGnssBatchingCbIface = nullptr;
+bool GnssBatching::sFlpSupportsBatching = false;
+
+FlpCallbacks GnssBatching::sFlpCb = {
+ .size = sizeof(FlpCallbacks),
+ .location_cb = locationCb,
+ .acquire_wakelock_cb = acquireWakelockCb,
+ .release_wakelock_cb = releaseWakelockCb,
+ .set_thread_event_cb = setThreadEventCb,
+ .flp_capabilities_cb = flpCapabilitiesCb,
+ .flp_status_cb = flpStatusCb,
+};
+
+GnssBatching::GnssBatching(const FlpLocationInterface* flpLocationIface) :
+ mFlpLocationIface(flpLocationIface) {
+}
+
+/*
+ * This enum is used locally by various methods below. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum BatchingValues : uint16_t {
+ // Numbers 0-3 were used in earlier implementations - using 4 to be distinct to the HAL
+ FLP_GNSS_BATCHING_CLIENT_ID = 4,
+ // Tech. mask of GNSS, and sensor aiding, for legacy HAL to fit with GnssBatching API
+ FLP_TECH_MASK_GNSS_AND_SENSORS = FLP_TECH_MASK_GNSS | FLP_TECH_MASK_SENSORS,
+ // Putting a cap to avoid possible memory issues. Unlikely values this high are supported.
+ MAX_LOCATIONS_PER_BATCH = 1000
+};
+
+void GnssBatching::locationCb(int32_t locationsCount, FlpLocation** locations) {
+ if (sGnssBatchingCbIface == nullptr) {
+ ALOGE("%s: GNSS Batching Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (locations == nullptr) {
+ ALOGE("%s: Invalid locations from GNSS HAL", __func__);
+ return;
+ }
+
+ if (locationsCount < 0) {
+ ALOGE("%s: Negative location count: %d set to 0", __func__, locationsCount);
+ locationsCount = 0;
+ } else if (locationsCount > MAX_LOCATIONS_PER_BATCH) {
+ ALOGW("%s: Unexpected high location count: %d set to %d", __func__, locationsCount,
+ MAX_LOCATIONS_PER_BATCH);
+ locationsCount = MAX_LOCATIONS_PER_BATCH;
+ }
+
+ /**
+ * Note:
+ * Some existing implementations may drop duplicate locations. These could be expanded here
+ * but as there's ambiguity between no-GPS-fix vs. dropped duplicates in that implementation,
+ * and that's not specified by the fused_location.h, that isn't safe to do here.
+ * Fortunately, this shouldn't be a major issue in cases where GNSS batching is typically
+ * used (e.g. when user is likely in vehicle/bicycle.)
+ */
+ std::vector<android::hardware::gnss::V1_0::GnssLocation> gnssLocations;
+ for (int iLocation = 0; iLocation < locationsCount; iLocation++) {
+ if (locations[iLocation] == nullptr) {
+ ALOGE("%s: Null location at slot: %d of %d, skipping", __func__, iLocation,
+ locationsCount);
+ continue;
+ }
+ if ((locations[iLocation]->sources_used & ~FLP_TECH_MASK_GNSS_AND_SENSORS) != 0)
+ {
+ ALOGE("%s: Unrequested location type %d at slot: %d of %d, skipping", __func__,
+ locations[iLocation]->sources_used, iLocation, locationsCount);
+ continue;
+ }
+ gnssLocations.push_back(convertToGnssLocation(locations[iLocation]));
+ }
+
+ auto ret = sGnssBatchingCbIface->gnssLocationBatchCb(gnssLocations);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssBatching::acquireWakelockCb() {
+ Gnss::acquireWakelockFused();
+}
+
+void GnssBatching::releaseWakelockCb() {
+ Gnss::releaseWakelockFused();
+}
+
+// this can just return success, because threads are now set up on demand in the jni layer
+int32_t GnssBatching::setThreadEventCb(ThreadEvent /*event*/) {
+ return FLP_RESULT_SUCCESS;
+}
+
+void GnssBatching::flpCapabilitiesCb(int32_t capabilities) {
+ ALOGD("%s capabilities %d", __func__, capabilities);
+
+ if (capabilities & CAPABILITY_GNSS) {
+ // once callback is received and capabilities high enough, we know version is
+ // high enough for flush()
+ sFlpSupportsBatching = true;
+ }
+}
+
+void GnssBatching::flpStatusCb(int32_t status) {
+ ALOGD("%s (default implementation) not forwarding status: %d", __func__, status);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching is unavailable", __func__);
+ return false;
+ }
+
+ sGnssBatchingCbIface = callback;
+
+ return (mFlpLocationIface->init(&sFlpCb) == 0);
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching interface is unavailable", __func__);
+ return 0;
+ }
+
+ return mFlpLocationIface->get_batch_size();
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching interface is unavailable", __func__);
+ return false;
+ }
+
+ if (!sFlpSupportsBatching) {
+ ALOGE("%s: Flp batching interface not supported, no capabilities callback received",
+ __func__);
+ return false;
+ }
+
+ FlpBatchOptions optionsHw;
+ // Legacy code used 9999 mW for High accuracy, and 21 mW for balanced.
+ // New GNSS API just expects reasonable GNSS chipset behavior - do something efficient
+ // given the interval. This 100 mW limit should be quite sufficient (esp. given legacy code
+ // implementations may not even use this value.)
+ optionsHw.max_power_allocation_mW = 100;
+ optionsHw.sources_to_use = FLP_TECH_MASK_GNSS_AND_SENSORS;
+ optionsHw.flags = 0;
+ if (options.flags & Flag::WAKEUP_ON_FIFO_FULL) {
+ optionsHw.flags |= FLP_BATCH_WAKEUP_ON_FIFO_FULL;
+ }
+ optionsHw.period_ns = options.periodNanos;
+ optionsHw.smallest_displacement_meters = 0; // Zero offset - just use time interval
+
+ return (mFlpLocationIface->start_batching(FLP_GNSS_BATCHING_CLIENT_ID, &optionsHw)
+ == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::flush() {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching interface is unavailable", __func__);
+ return Void();
+ }
+
+ mFlpLocationIface->flush_batched_locations();
+
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching interface is unavailable", __func__);
+ return false;
+ }
+
+ return (mFlpLocationIface->stop_batching(FLP_GNSS_BATCHING_CLIENT_ID) == FLP_RESULT_SUCCESS);
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mFlpLocationIface == nullptr) {
+ ALOGE("%s: Flp batching interface is unavailable", __func__);
+ return Void();
+ }
+
+ mFlpLocationIface->cleanup();
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssBatching.h b/gnss/1.0/GnssBatching.h
new file mode 100644
index 0000000..001c27d
--- /dev/null
+++ b/gnss/1.0/GnssBatching.h
@@ -0,0 +1,67 @@
+#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 <hardware/fused_location.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::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;
+
+struct GnssBatching : public IGnssBatching {
+ GnssBatching(const FlpLocationInterface* flpLocationIface);
+
+ // 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;
+
+ /*
+ * Callback methods to be passed into the conventional FLP HAL by the default
+ * implementation. These methods are not part of the IGnssBatching base class.
+ */
+ static void locationCb(int32_t locationsCount, FlpLocation** locations);
+ static void acquireWakelockCb();
+ static void releaseWakelockCb();
+ static int32_t setThreadEventCb(ThreadEvent event);
+ static void flpCapabilitiesCb(int32_t capabilities);
+ static void flpStatusCb(int32_t status);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static FlpCallbacks sFlpCb;
+
+ private:
+ const FlpLocationInterface* mFlpLocationIface = nullptr;
+ static sp<IGnssBatchingCallback> sGnssBatchingCbIface;
+ static bool sFlpSupportsBatching;
+};
+
+extern "C" IGnssBatching* HIDL_FETCH_IGnssBatching(const char* name);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/gnss/1.0/GnssConfiguration.cpp b/gnss/1.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..0c1aa86
--- /dev/null
+++ b/gnss/1.0/GnssConfiguration.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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_GnssConfigurationInterface"
+
+#include <log/log.h>
+
+#include "GnssConfiguration.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssConfiguration::GnssConfiguration(const GnssConfigurationInterface* gnssConfigInfc)
+ : mGnssConfigIface(gnssConfigInfc) {}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "SUPL_ES=" + std::to_string(enabled ? 1 : 0) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "SUPL_VER=" + std::to_string(version) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+
+ return true;
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "SUPL_MODE=" + std::to_string(mode) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "LPP_PROFILE=" + std::to_string(lppProfile) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "A_GLONASS_POS_PROTOCOL_SELECT=" +
+ std::to_string(protocol) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "GPS_LOCK=" + std::to_string(lock) + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnssConfigIface == nullptr) {
+ ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+ return false;
+ }
+
+ std::string config = "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=" + std::to_string(enabled ? 1 : 0)
+ + "\n";
+ mGnssConfigIface->configuration_update(config.c_str(), config.size());
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssConfiguration.h b/gnss/1.0/GnssConfiguration.h
new file mode 100644
index 0000000..a6eca88
--- /dev/null
+++ b/gnss/1.0/GnssConfiguration.h
@@ -0,0 +1,66 @@
+/*
+ * 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 <hardware/gps.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 GnssConfiguration : public IGnssConfiguration {
+ GnssConfiguration(const GnssConfigurationInterface* gnssConfigIface);
+
+ /*
+ * 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 lppProfile) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ private:
+ const GnssConfigurationInterface* mGnssConfigIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssConfiguration_H_
diff --git a/gnss/1.0/GnssDebug.cpp b/gnss/1.0/GnssDebug.cpp
new file mode 100644
index 0000000..cfc38ca
--- /dev/null
+++ b/gnss/1.0/GnssDebug.cpp
@@ -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.
+ */
+
+#define LOG_TAG "GnssHAL_GnssDebugInterface"
+
+#include <log/log.h>
+
+#include "GnssDebug.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssDebug::GnssDebug(const GpsDebugInterface* gpsDebugIface) : mGnssDebugIface(gpsDebugIface) {}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb) {
+ /*
+ * This is a new interface and hence there is no way to retrieve the
+ * debug data from the HAL.
+ */
+ DebugData data = {};
+
+ _hidl_cb(data);
+
+ /*
+ * Log the debug data sent from the conventional Gnss HAL. This code is
+ * moved here from GnssLocationProvider.
+ */
+ if (mGnssDebugIface) {
+ char buffer[kMaxDebugStrLen + 1];
+ size_t length = mGnssDebugIface->get_internal_state(buffer, kMaxDebugStrLen);
+ length = std::max(length, kMaxDebugStrLen);
+ buffer[length] = '\0';
+ ALOGD("Gnss Debug Data: %s", buffer);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssDebug.h b/gnss/1.0/GnssDebug.h
new file mode 100644
index 0000000..9a17dde
--- /dev/null
+++ b/gnss/1.0/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * 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>
+#include <hardware/gps.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 GnssDebug : public IGnssDebug {
+ GnssDebug(const GpsDebugInterface* gpsDebugIface);
+
+ /*
+ * 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:
+ /*
+ * Constant added for backward compatibility to conventional GPS Hals which
+ * returned a debug string.
+ */
+ const size_t kMaxDebugStrLen = 2047;
+ const GpsDebugInterface* mGnssDebugIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssDebug_H_
diff --git a/gnss/1.0/GnssGeofencing.cpp b/gnss/1.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..54c4aaa
--- /dev/null
+++ b/gnss/1.0/GnssGeofencing.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include "GnssGeofencing.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList;
+sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr;
+bool GnssGeofencing::sInterfaceExists = false;
+
+GpsGeofenceCallbacks GnssGeofencing::sGnssGfCb = {
+ .geofence_transition_callback = gnssGfTransitionCb,
+ .geofence_status_callback = gnssGfStatusCb,
+ .geofence_add_callback = gnssGfAddCb,
+ .geofence_remove_callback = gnssGfRemoveCb,
+ .geofence_pause_callback = gnssGfPauseCb,
+ .geofence_resume_callback = gnssGfResumeCb,
+ .create_thread_cb = createThreadCb
+};
+
+GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface)
+ : mGnssGeofencingIface(gpsGeofencingIface) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ sThreadFuncArgsList.clear();
+ sInterfaceExists = false;
+}
+void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId,
+ GpsLocation* location,
+ int32_t transition,
+ GpsUtcTime timestamp) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (location == nullptr) {
+ ALOGE("%s : Invalid location from GNSS HAL", __func__);
+ return;
+ }
+
+ GnssLocation gnssLocation = convertToGnssLocation(location);
+ auto ret = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceId,
+ gnssLocation,
+ static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition),
+ timestamp);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation* location) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ GnssLocation gnssLocation;
+
+ if (location != nullptr) {
+ gnssLocation = convertToGnssLocation(location);
+ } else {
+ gnssLocation = {};
+ }
+
+ auto ret = mGnssGeofencingCbIface->gnssGeofenceStatusCb(
+ static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = mGnssGeofencingCbIface->gnssGeofenceAddCb(
+ geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(
+ geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = mGnssGeofencingCbIface->gnssGeofencePauseCb(
+ geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) {
+ if (mGnssGeofencingCbIface == nullptr) {
+ ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = mGnssGeofencingCbIface->gnssGeofenceResumeCb(
+ geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ mGnssGeofencingCbIface = callback;
+
+ if (mGnssGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface is not available", __func__);
+ } else {
+ mGnssGeofencingIface->init(&sGnssGfCb);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mGnssGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface is not available", __func__);
+ return Void();
+ } else {
+ mGnssGeofencingIface->add_geofence_area(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mGnssGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface is not available", __func__);
+ } else {
+ mGnssGeofencingIface->pause_geofence(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mGnssGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface is not available", __func__);
+ } else {
+ mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mGnssGeofencingIface == nullptr) {
+ ALOGE("%s: GnssGeofencing interface is not available", __func__);
+ } else {
+ mGnssGeofencingIface->remove_geofence_area(geofenceId);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssGeofencing.h b/gnss/1.0/GnssGeofencing.h
new file mode 100644
index 0000000..124b893
--- /dev/null
+++ b/gnss/1.0/GnssGeofencing.h
@@ -0,0 +1,97 @@
+/*
+ * 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 <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+#include <hardware/gps.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;
+
+/*
+ * Interface for GNSS Geofencing support. It also contains wrapper methods to allow
+ * methods from IGnssGeofenceCallback interface to be passed into the
+ * conventional implementation of the GNSS HAL.
+ */
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface);
+ ~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;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default
+ * implementation. These methods are not part of the IGnssGeofencing base class.
+ */
+ static void gnssGfTransitionCb(int32_t geofence_id, GpsLocation* location,
+ int32_t transition, GpsUtcTime timestamp);
+ static void gnssGfStatusCb(int32_t status, GpsLocation* last_location);
+ static void gnssGfAddCb(int32_t geofence_id, int32_t status);
+ static void gnssGfRemoveCb(int32_t geofence_id, int32_t status);
+ static void gnssGfPauseCb(int32_t geofence_id, int32_t status);
+ static void gnssGfResumeCb(int32_t geofence_id, int32_t status);
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsGeofenceCallbacks sGnssGfCb;
+
+ private:
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static sp<IGnssGeofenceCallback> mGnssGeofencingCbIface;
+ const GpsGeofencingInterface* mGnssGeofencingIface = nullptr;
+ static bool sInterfaceExists;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssGeofencing_H_
diff --git a/gnss/1.0/GnssMeasurement.cpp b/gnss/1.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..d81f829
--- /dev/null
+++ b/gnss/1.0/GnssMeasurement.cpp
@@ -0,0 +1,260 @@
+/*
+ * 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_GnssMeasurementInterface"
+
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssMeasurementCallback> GnssMeasurement::sGnssMeasureCbIface = nullptr;
+GpsMeasurementCallbacks GnssMeasurement::sGnssMeasurementCbs = {
+ .size = sizeof(GpsMeasurementCallbacks),
+ .measurement_callback = gpsMeasurementCb,
+ .gnss_measurement_callback = gnssMeasurementCb
+};
+
+GnssMeasurement::GnssMeasurement(const GpsMeasurementInterface* gpsMeasurementIface)
+ : mGnssMeasureIface(gpsMeasurementIface) {}
+
+void GnssMeasurement::gnssMeasurementCb(LegacyGnssData* legacyGnssData) {
+ if (sGnssMeasureCbIface == nullptr) {
+ ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (legacyGnssData == nullptr) {
+ ALOGE("%s: Invalid GnssData from GNSS HAL", __func__);
+ return;
+ }
+
+ IGnssMeasurementCallback::GnssData gnssData;
+ gnssData.measurementCount = std::min(legacyGnssData->measurement_count,
+ static_cast<size_t>(GnssMax::SVS_COUNT));
+
+ for (size_t i = 0; i < gnssData.measurementCount; i++) {
+ auto entry = legacyGnssData->measurements[i];
+ auto state = static_cast<GnssMeasurementState>(entry.state);
+ if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED) {
+ state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+ }
+ if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED) {
+ state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+ }
+ gnssData.measurements[i] = {
+ .flags = entry.flags,
+ .svid = entry.svid,
+ .constellation = static_cast<GnssConstellationType>(entry.constellation),
+ .timeOffsetNs = entry.time_offset_ns,
+ .state = state,
+ .receivedSvTimeInNs = entry.received_sv_time_in_ns,
+ .receivedSvTimeUncertaintyInNs = entry.received_sv_time_uncertainty_in_ns,
+ .cN0DbHz = entry.c_n0_dbhz,
+ .pseudorangeRateMps = entry.pseudorange_rate_mps,
+ .pseudorangeRateUncertaintyMps = entry.pseudorange_rate_uncertainty_mps,
+ .accumulatedDeltaRangeState = entry.accumulated_delta_range_state,
+ .accumulatedDeltaRangeM = entry.accumulated_delta_range_m,
+ .accumulatedDeltaRangeUncertaintyM = entry.accumulated_delta_range_uncertainty_m,
+ .carrierFrequencyHz = entry.carrier_frequency_hz,
+ .carrierCycles = entry.carrier_cycles,
+ .carrierPhase = entry.carrier_phase,
+ .carrierPhaseUncertainty = entry.carrier_phase_uncertainty,
+ .multipathIndicator = static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+ entry.multipath_indicator),
+ .snrDb = entry.snr_db
+ };
+ }
+
+ auto clockVal = legacyGnssData->clock;
+ gnssData.clock = {
+ .gnssClockFlags = clockVal.flags,
+ .leapSecond = clockVal.leap_second,
+ .timeNs = clockVal.time_ns,
+ .timeUncertaintyNs = clockVal.time_uncertainty_ns,
+ .fullBiasNs = clockVal.full_bias_ns,
+ .biasNs = clockVal.bias_ns,
+ .biasUncertaintyNs = clockVal.bias_uncertainty_ns,
+ .driftNsps = clockVal.drift_nsps,
+ .driftUncertaintyNsps = clockVal.drift_uncertainty_nsps,
+ .hwClockDiscontinuityCount = clockVal.hw_clock_discontinuity_count
+ };
+
+ auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+/*
+ * The code in the following method has been moved here from GnssLocationProvider.
+ * It converts GpsData to GnssData. This code is no longer required in
+ * GnssLocationProvider since GpsData is deprecated and no longer part of the
+ * GNSS interface.
+ */
+void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
+ if (sGnssMeasureCbIface == nullptr) {
+ ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (gpsData == nullptr) {
+ ALOGE("%s: Invalid GpsData from GNSS HAL", __func__);
+ return;
+ }
+
+ IGnssMeasurementCallback::GnssData gnssData;
+ gnssData.measurementCount = std::min(gpsData->measurement_count,
+ static_cast<size_t>(GnssMax::SVS_COUNT));
+
+
+ for (size_t i = 0; i < gnssData.measurementCount; i++) {
+ auto entry = gpsData->measurements[i];
+ gnssData.measurements[i].flags = entry.flags;
+ gnssData.measurements[i].svid = static_cast<int32_t>(entry.prn);
+ if (entry.prn >= 1 && entry.prn <= 32) {
+ gnssData.measurements[i].constellation = GnssConstellationType::GPS;
+ } else {
+ gnssData.measurements[i].constellation =
+ GnssConstellationType::UNKNOWN;
+ }
+
+ gnssData.measurements[i].timeOffsetNs = entry.time_offset_ns;
+ gnssData.measurements[i].state = entry.state;
+ gnssData.measurements[i].receivedSvTimeInNs = entry.received_gps_tow_ns;
+ gnssData.measurements[i].receivedSvTimeUncertaintyInNs =
+ entry.received_gps_tow_uncertainty_ns;
+ gnssData.measurements[i].cN0DbHz = entry.c_n0_dbhz;
+ gnssData.measurements[i].pseudorangeRateMps = entry.pseudorange_rate_mps;
+ gnssData.measurements[i].pseudorangeRateUncertaintyMps =
+ entry.pseudorange_rate_uncertainty_mps;
+ gnssData.measurements[i].accumulatedDeltaRangeState =
+ entry.accumulated_delta_range_state;
+ gnssData.measurements[i].accumulatedDeltaRangeM =
+ entry.accumulated_delta_range_m;
+ gnssData.measurements[i].accumulatedDeltaRangeUncertaintyM =
+ entry.accumulated_delta_range_uncertainty_m;
+
+ if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
+ gnssData.measurements[i].carrierFrequencyHz = entry.carrier_frequency_hz;
+ } else {
+ gnssData.measurements[i].carrierFrequencyHz = 0;
+ }
+
+ if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE) {
+ gnssData.measurements[i].carrierPhase = entry.carrier_phase;
+ } else {
+ gnssData.measurements[i].carrierPhase = 0;
+ }
+
+ if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
+ gnssData.measurements[i].carrierPhaseUncertainty = entry.carrier_phase_uncertainty;
+ } else {
+ gnssData.measurements[i].carrierPhaseUncertainty = 0;
+ }
+
+ gnssData.measurements[i].multipathIndicator =
+ static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+ entry.multipath_indicator);
+
+ if (entry.flags & GNSS_MEASUREMENT_HAS_SNR) {
+ gnssData.measurements[i].snrDb = entry.snr_db;
+ } else {
+ gnssData.measurements[i].snrDb = 0;
+ }
+ }
+
+ auto clockVal = gpsData->clock;
+ static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
+
+ gnssData.clock.leapSecond = clockVal.leap_second;
+ /*
+ * GnssClock only supports the more effective HW_CLOCK type, so type
+ * handling and documentation complexity has been removed. To convert the
+ * old GPS_CLOCK types (active only in a limited number of older devices),
+ * the GPS time information is handled as an always discontinuous HW clock,
+ * with the GPS time information put into the full_bias_ns instead - so that
+ * time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
+ * sign of full_bias_ns and bias_ns has flipped between GpsClock &
+ * GnssClock, so that is also handled below.
+ */
+ switch (clockVal.type) {
+ case GPS_CLOCK_TYPE_UNKNOWN:
+ // Clock type unsupported.
+ ALOGE("Unknown clock type provided.");
+ break;
+ case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
+ // Already local hardware time. No need to do anything.
+ break;
+ case GPS_CLOCK_TYPE_GPS_TIME:
+ // GPS time, need to convert.
+ clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
+ clockVal.full_bias_ns = clockVal.time_ns;
+ clockVal.time_ns = 0;
+ gnssData.clock.hwClockDiscontinuityCount =
+ discontinuity_count_to_handle_old_clock_type++;
+ break;
+ }
+
+ gnssData.clock.timeNs = clockVal.time_ns;
+ gnssData.clock.timeUncertaintyNs = clockVal.time_uncertainty_ns;
+ /*
+ * Definition of sign for full_bias_ns & bias_ns has been changed since N,
+ * so flip signs here.
+ */
+ gnssData.clock.fullBiasNs = -(clockVal.full_bias_ns);
+ gnssData.clock.biasNs = -(clockVal.bias_ns);
+ gnssData.clock.biasUncertaintyNs = clockVal.bias_uncertainty_ns;
+ gnssData.clock.driftNsps = clockVal.drift_nsps;
+ gnssData.clock.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps;
+ gnssData.clock.gnssClockFlags = clockVal.flags;
+
+ auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<IGnssMeasurementCallback>& callback) {
+ if (mGnssMeasureIface == nullptr) {
+ ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+ return GnssMeasurementStatus::ERROR_GENERIC;
+ }
+ sGnssMeasureCbIface = callback;
+
+ return static_cast<GnssMeasurement::GnssMeasurementStatus>(
+ mGnssMeasureIface->init(&sGnssMeasurementCbs));
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mGnssMeasureIface == nullptr) {
+ ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+ } else {
+ mGnssMeasureIface->close();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssMeasurement.h b/gnss/1.0/GnssMeasurement.h
new file mode 100644
index 0000000..9ff1435
--- /dev/null
+++ b/gnss/1.0/GnssMeasurement.h
@@ -0,0 +1,84 @@
+/*
+ * 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 <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <hidl/Status.h>
+#include <hardware/gps.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;
+
+using LegacyGnssData = ::GnssData;
+
+/*
+ * Extended interface for GNSS Measurements support. Also contains wrapper methods to allow methods
+ * from IGnssMeasurementCallback interface to be passed into the conventional implementation of the
+ * GNSS HAL.
+ */
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement(const GpsMeasurementInterface* gpsMeasurementIface);
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurementStatus> setCallback(
+ const sp<IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default
+ * implementation. These methods are not part of the IGnssMeasurement base class.
+ */
+ static void gnssMeasurementCb(LegacyGnssData* data);
+ /*
+ * Deprecated callback added for backward compatibity for devices that do
+ * not support GnssData measurements.
+ */
+ static void gpsMeasurementCb(GpsData* data);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsMeasurementCallbacks sGnssMeasurementCbs;
+
+ private:
+ const GpsMeasurementInterface* mGnssMeasureIface = nullptr;
+ static sp<IGnssMeasurementCallback> sGnssMeasureCbIface;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssMeasurement_H_
diff --git a/gnss/1.0/GnssNavigationMessage.cpp b/gnss/1.0/GnssNavigationMessage.cpp
new file mode 100644
index 0000000..6f509d0
--- /dev/null
+++ b/gnss/1.0/GnssNavigationMessage.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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_GnssNavigationMessageInterface"
+
+#include <log/log.h>
+
+#include "GnssNavigationMessage.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssNavigationMessageCallback> GnssNavigationMessage::sGnssNavigationMsgCbIface = nullptr;
+
+GpsNavigationMessageCallbacks GnssNavigationMessage::sGnssNavigationMessageCb = {
+ .size = sizeof(GpsNavigationMessageCallbacks),
+ .navigation_message_callback = nullptr,
+ .gnss_navigation_message_callback = gnssNavigationMessageCb
+};
+
+GnssNavigationMessage::GnssNavigationMessage(
+ const GpsNavigationMessageInterface* gpsNavigationMessageIface) :
+ mGnssNavigationMessageIface(gpsNavigationMessageIface) {}
+
+void GnssNavigationMessage::gnssNavigationMessageCb(LegacyGnssNavigationMessage* message) {
+ if (sGnssNavigationMsgCbIface == nullptr) {
+ ALOGE("%s: GnssNavigation Message Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (message == nullptr) {
+ ALOGE("%s, received invalid GnssNavigationMessage from GNSS HAL", __func__);
+ return;
+ }
+
+ IGnssNavigationMessageCallback::GnssNavigationMessage navigationMsg;
+
+ navigationMsg.svid = message->svid;
+ navigationMsg.type =
+ static_cast<IGnssNavigationMessageCallback::GnssNavigationMessageType>(message->type);
+ navigationMsg.status = message->status;
+ navigationMsg.messageId = message->message_id;
+ navigationMsg.submessageId = message->submessage_id;
+ navigationMsg.data.setToExternal(message->data, message->data_length);
+
+ auto ret = sGnssNavigationMsgCbIface->gnssNavigationMessageCb(navigationMsg);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+Return<GnssNavigationMessage::GnssNavigationMessageStatus> GnssNavigationMessage::setCallback(
+ const sp<IGnssNavigationMessageCallback>& callback) {
+ if (mGnssNavigationMessageIface == nullptr) {
+ ALOGE("%s: GnssNavigationMessage not available", __func__);
+ return GnssNavigationMessageStatus::ERROR_GENERIC;
+ }
+
+ sGnssNavigationMsgCbIface = callback;
+
+ return static_cast<GnssNavigationMessage::GnssNavigationMessageStatus>(
+ mGnssNavigationMessageIface->init(&sGnssNavigationMessageCb));
+}
+
+Return<void> GnssNavigationMessage::close() {
+ if (mGnssNavigationMessageIface == nullptr) {
+ ALOGE("%s: GnssNavigationMessage not available", __func__);
+ } else {
+ mGnssNavigationMessageIface->close();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssNavigationMessage.h b/gnss/1.0/GnssNavigationMessage.h
new file mode 100644
index 0000000..882854b
--- /dev/null
+++ b/gnss/1.0/GnssNavigationMessage.h
@@ -0,0 +1,77 @@
+/*
+ * 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_GnssNavigationMessage_H_
+#define android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssNavigationMessage = ::GnssNavigationMessage;
+
+/*
+ * Extended interface for GNSS navigation message reporting support. Also contains wrapper methods
+ * to allow methods from IGnssNavigationMessageCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct GnssNavigationMessage : public IGnssNavigationMessage {
+ GnssNavigationMessage(const GpsNavigationMessageInterface* gpsNavigationMessageIface);
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+ * These declarations were generated from IGnssNavigationMessage.hal.
+ */
+ Return<GnssNavigationMessageStatus> setCallback(
+ const sp<IGnssNavigationMessageCallback>& callback) override;
+ Return<void> close() override;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+ * These methods are not part of the IGnssNavigationMessage base class.
+ */
+ static void gnssNavigationMessageCb(LegacyGnssNavigationMessage* message);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsNavigationMessageCallbacks sGnssNavigationMessageCb;
+ private:
+ const GpsNavigationMessageInterface* mGnssNavigationMessageIface = nullptr;
+ static sp<IGnssNavigationMessageCallback> sGnssNavigationMsgCbIface;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssNavigationMessage_H_
diff --git a/gnss/1.0/GnssNi.cpp b/gnss/1.0/GnssNi.cpp
new file mode 100644
index 0000000..d17891d
--- /dev/null
+++ b/gnss/1.0/GnssNi.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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_GnssNiInterface"
+
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssNi::sThreadFuncArgsList;
+sp<IGnssNiCallback> GnssNi::sGnssNiCbIface = nullptr;
+bool GnssNi::sInterfaceExists = false;
+
+GpsNiCallbacks GnssNi::sGnssNiCb = {
+ .notify_cb = niNotifyCb,
+ .create_thread_cb = createThreadCb
+};
+
+GnssNi::GnssNi(const GpsNiInterface* gpsNiIface) : mGnssNiIface(gpsNiIface) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+}
+
+GnssNi::~GnssNi() {
+ sThreadFuncArgsList.clear();
+ sInterfaceExists = false;
+}
+
+pthread_t GnssNi::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void GnssNi::niNotifyCb(GpsNiNotification* notification) {
+ if (sGnssNiCbIface == nullptr) {
+ ALOGE("%s: GNSS NI Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ if (notification == nullptr) {
+ ALOGE("%s: Invalid GpsNotification callback from GNSS HAL", __func__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {
+ .notificationId = notification->notification_id,
+ .niType = static_cast<IGnssNiCallback::GnssNiType>(notification->ni_type),
+ .notifyFlags = notification->notify_flags,
+ .timeoutSec = static_cast<uint32_t>(notification->timeout),
+ .defaultResponse =
+ static_cast<IGnssNiCallback::GnssUserResponseType>(notification->default_response),
+ .requestorId = notification->requestor_id,
+ .notificationMessage = notification->text,
+ .requestorIdEncoding =
+ static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->requestor_id_encoding),
+ .notificationIdEncoding =
+ static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->text_encoding)
+ };
+
+ auto ret = sGnssNiCbIface->niNotifyCb(notificationGnss);
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnssNiIface == nullptr) {
+ ALOGE("%s: GnssNi interface is unavailable", __func__);
+ return Void();
+ }
+
+ sGnssNiCbIface = callback;
+
+ mGnssNiIface->init(&sGnssNiCb);
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnssNiIface == nullptr) {
+ ALOGE("%s: GnssNi interface is unavailable", __func__);
+ } else {
+ mGnssNiIface->respond(notifId, static_cast<GpsUserResponseType>(userResponse));
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssNi.h b/gnss/1.0/GnssNi.h
new file mode 100644
index 0000000..fe850b1
--- /dev/null
+++ b/gnss/1.0/GnssNi.h
@@ -0,0 +1,81 @@
+/*
+ * 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 <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+#include <hardware/gps.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;
+
+/*
+ * Extended interface for Network-initiated (NI) support. This interface is used to respond to
+ * NI notifications originating from the HAL. Also contains wrapper methods to allow methods from
+ * IGnssNiCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct GnssNi : public IGnssNi {
+ GnssNi(const GpsNiInterface* gpsNiIface);
+ ~GnssNi();
+
+ /*
+ * 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;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default
+ * implementation. These methods are not part of the IGnssNi base class.
+ */
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+ static void niNotifyCb(GpsNiNotification* notification);
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsNiCallbacks sGnssNiCb;
+
+ private:
+ const GpsNiInterface* mGnssNiIface = nullptr;
+ static sp<IGnssNiCallback> sGnssNiCbIface;
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static bool sInterfaceExists;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssNi_H_
diff --git a/gnss/1.0/GnssUtils.cpp b/gnss/1.0/GnssUtils.cpp
new file mode 100644
index 0000000..4514a21
--- /dev/null
+++ b/gnss/1.0/GnssUtils.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include "GnssUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using android::hardware::gnss::V1_0::GnssLocation;
+
+GnssLocation convertToGnssLocation(GpsLocation* location) {
+ GnssLocation gnssLocation = {};
+ if (location != nullptr) {
+ gnssLocation = {
+ // Bit operation AND with 1f below is needed to clear vertical accuracy,
+ // speed accuracy and bearing accuracy flags as some vendors are found
+ // to be setting these bits in pre-Android-O devices
+ .gnssLocationFlags = static_cast<uint16_t>(location->flags & 0x1f),
+ .latitudeDegrees = location->latitude,
+ .longitudeDegrees = location->longitude,
+ .altitudeMeters = location->altitude,
+ .speedMetersPerSec = location->speed,
+ .bearingDegrees = location->bearing,
+ .horizontalAccuracyMeters = location->accuracy,
+ // Older chipsets do not provide the following 3 fields, hence the flags
+ // HAS_VERTICAL_ACCURACY, HAS_SPEED_ACCURACY and HAS_BEARING_ACCURACY are
+ // not set and the field are set to zeros.
+ .verticalAccuracyMeters = 0,
+ .speedAccuracyMetersPerSecond = 0,
+ .bearingAccuracyDegrees = 0,
+ .timestamp = location->timestamp
+ };
+ }
+
+ return gnssLocation;
+}
+
+GnssLocation convertToGnssLocation(FlpLocation* flpLocation) {
+ GnssLocation gnssLocation = {};
+ if (flpLocation != nullptr) {
+ gnssLocation = {.gnssLocationFlags = 0, // clear here and set below
+ .latitudeDegrees = flpLocation->latitude,
+ .longitudeDegrees = flpLocation->longitude,
+ .altitudeMeters = flpLocation->altitude,
+ .speedMetersPerSec = flpLocation->speed,
+ .bearingDegrees = flpLocation->bearing,
+ .horizontalAccuracyMeters = flpLocation->accuracy,
+ .verticalAccuracyMeters = 0,
+ .speedAccuracyMetersPerSecond = 0,
+ .bearingAccuracyDegrees = 0,
+ .timestamp = flpLocation->timestamp};
+ // FlpLocation flags different from GnssLocation flags
+ if (flpLocation->flags & FLP_LOCATION_HAS_LAT_LONG) {
+ gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_LAT_LONG;
+ }
+ if (flpLocation->flags & FLP_LOCATION_HAS_ALTITUDE) {
+ gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_ALTITUDE;
+ }
+ if (flpLocation->flags & FLP_LOCATION_HAS_SPEED) {
+ gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_SPEED;
+ }
+ if (flpLocation->flags & FLP_LOCATION_HAS_BEARING) {
+ gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_BEARING;
+ }
+ if (flpLocation->flags & FLP_LOCATION_HAS_ACCURACY) {
+ gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+ }
+ }
+
+ return gnssLocation;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssUtils.h b/gnss/1.0/GnssUtils.h
new file mode 100644
index 0000000..38d4b2d
--- /dev/null
+++ b/gnss/1.0/GnssUtils.h
@@ -0,0 +1,47 @@
+/*
+ * 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_GnssUtil_H_
+#define android_hardware_gnss_V1_0_GnssUtil_H_
+
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * This method converts a GpsLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(GpsLocation* location);
+
+/*
+ * This method converts an FlpLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(FlpLocation* location);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/gnss/1.0/GnssXtra.cpp b/gnss/1.0/GnssXtra.cpp
new file mode 100644
index 0000000..d124ce1
--- /dev/null
+++ b/gnss/1.0/GnssXtra.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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_GnssXtraInterface"
+
+#include "GnssXtra.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssXtra::sThreadFuncArgsList;
+sp<IGnssXtraCallback> GnssXtra::sGnssXtraCbIface = nullptr;
+bool GnssXtra::sInterfaceExists = false;
+
+GpsXtraCallbacks GnssXtra::sGnssXtraCb = {
+ .download_request_cb = gnssXtraDownloadRequestCb,
+ .create_thread_cb = createThreadCb,
+};
+
+GnssXtra::~GnssXtra() {
+ sThreadFuncArgsList.clear();
+ sInterfaceExists = false;
+}
+
+pthread_t GnssXtra::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+ return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+GnssXtra::GnssXtra(const GpsXtraInterface* xtraIface) : mGnssXtraIface(xtraIface) {
+ /* Error out if an instance of the interface already exists. */
+ LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+ sInterfaceExists = true;
+}
+
+void GnssXtra::gnssXtraDownloadRequestCb() {
+ if (sGnssXtraCbIface == nullptr) {
+ ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+ return;
+ }
+
+ auto ret = sGnssXtraCbIface->downloadRequestCb();
+ if (!ret.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+Return<bool> GnssXtra::setCallback(const sp<IGnssXtraCallback>& callback) {
+ if (mGnssXtraIface == nullptr) {
+ ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+ return false;
+ }
+
+ sGnssXtraCbIface = callback;
+
+ return (mGnssXtraIface->init(&sGnssXtraCb) == 0);
+}
+
+Return<bool> GnssXtra::injectXtraData(const hidl_string& xtraData) {
+ if (mGnssXtraIface == nullptr) {
+ ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+ return false;
+ }
+
+ char* buf = new char[xtraData.size()];
+ const char* data = xtraData.c_str();
+
+ memcpy(buf, data, xtraData.size());
+
+ int ret = mGnssXtraIface->inject_xtra_data(buf, xtraData.size());
+ delete[] buf;
+ return (ret == 0);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/1.0/GnssXtra.h b/gnss/1.0/GnssXtra.h
new file mode 100644
index 0000000..7a0733a
--- /dev/null
+++ b/gnss/1.0/GnssXtra.h
@@ -0,0 +1,80 @@
+/*
+ * 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_GnssXtra_H_
+#define android_hardware_gnss_V1_0_GnssXtra_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssXtra.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssXtra;
+using ::android::hardware::gnss::V1_0::IGnssXtraCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * This interface is used by the GNSS HAL to request the framework to download XTRA data.
+ * Also contains wrapper methods to allow methods from IGnssXtraCallback interface to be passed
+ * into the conventional implementation of the GNSS HAL.
+ */
+struct GnssXtra : public IGnssXtra {
+ GnssXtra(const GpsXtraInterface* xtraIface);
+ ~GnssXtra();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+ * These declarations were generated from IGnssXtra.hal.
+ */
+ Return<bool> setCallback(const sp<IGnssXtraCallback>& callback) override;
+ Return<bool> injectXtraData(const hidl_string& xtraData) override;
+
+ /*
+ * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+ * These methods are not part of the IGnssXtra base class.
+ */
+ static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+ static void gnssXtraDownloadRequestCb();
+
+ /*
+ * Holds function pointers to the callback methods.
+ */
+ static GpsXtraCallbacks sGnssXtraCb;
+
+ private:
+ const GpsXtraInterface* mGnssXtraIface = nullptr;
+ static sp<IGnssXtraCallback> sGnssXtraCbIface;
+ static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+ static bool sInterfaceExists;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_V1_0_GnssXtra_H_
diff --git a/gnss/1.0/OWNERS b/gnss/1.0/OWNERS
new file mode 100644
index 0000000..6c25bd7
--- /dev/null
+++ b/gnss/1.0/OWNERS
@@ -0,0 +1,3 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
diff --git a/gnss/1.0/ThreadCreationWrapper.cpp b/gnss/1.0/ThreadCreationWrapper.cpp
new file mode 100644
index 0000000..2a5638f
--- /dev/null
+++ b/gnss/1.0/ThreadCreationWrapper.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#include <ThreadCreationWrapper.h>
+
+void* threadFunc(void* arg) {
+ ThreadFuncArgs* threadArgs = reinterpret_cast<ThreadFuncArgs*>(arg);
+ threadArgs->fptr(threadArgs->args);
+ return nullptr;
+}
+
+pthread_t createPthread(const char* name,
+ void (*start)(void*),
+ void* arg, std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs) {
+ pthread_t threadId;
+ auto threadArgs = new ThreadFuncArgs(start, arg);
+ auto argPtr = std::unique_ptr<ThreadFuncArgs>(threadArgs);
+
+ listArgs->push_back(std::move(argPtr));
+
+ int ret = pthread_create(&threadId, nullptr, threadFunc, reinterpret_cast<void*>(
+ threadArgs));
+ if (ret != 0) {
+ ALOGE("pthread creation unsuccessful");
+ } else {
+ pthread_setname_np(threadId, name);
+ }
+ return threadId;
+}
diff --git a/gnss/1.0/ThreadCreationWrapper.h b/gnss/1.0/ThreadCreationWrapper.h
new file mode 100644
index 0000000..f401ce2
--- /dev/null
+++ b/gnss/1.0/ThreadCreationWrapper.h
@@ -0,0 +1,58 @@
+/*
+ * 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_THREADCREATIONWRAPPER_H
+#define ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+
+#include <log/log.h>
+#include <pthread.h>
+#include <vector>
+
+typedef void (*threadEntryFunc)(void* ret);
+
+/*
+ * This class facilitates createThreadCb methods in various GNSS interfaces to wrap
+ * pthread_create() from libc since its function signature differs from what is required by the
+ * conventional GNSS HAL. The arguments passed to pthread_create() need to be on heap and not on
+ * the stack of createThreadCb.
+ */
+struct ThreadFuncArgs {
+ ThreadFuncArgs(void (*start)(void*), void* arg) : fptr(start), args(arg) {}
+
+ /* pointer to the function of type void()(void*) that needs to be wrapped */
+ threadEntryFunc fptr;
+ /* argument for fptr to be called with */
+ void* args;
+};
+
+/*
+ * This method is simply a wrapper. It is required since pthread_create() requires an entry
+ * function pointer of type void*()(void*) and the GNSS hal requires as input a function pointer of
+ * type void()(void*).
+ */
+void* threadFunc(void* arg);
+
+/*
+ * This method is called by createThreadCb with a pointer to the vector that
+ * holds the pointers to the thread arguments. The arg and start parameters are
+ * first used to create a ThreadFuncArgs object which is then saved in the
+ * listArgs parameters. The created ThreadFuncArgs object is then used to invoke
+ * threadFunc() method which in-turn invokes pthread_create.
+ */
+pthread_t createPthread(const char* name, void (*start)(void*), void* arg,
+ std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs);
+
+#endif
diff --git a/gnss/1.0/android.hardware.gnss@1.0-service.rc b/gnss/1.0/android.hardware.gnss@1.0-service.rc
new file mode 100644
index 0000000..1a44d34
--- /dev/null
+++ b/gnss/1.0/android.hardware.gnss@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service
+ class hal
+ user gps
+ group system gps radio
diff --git a/gnss/1.0/service.cpp b/gnss/1.0/service.cpp
new file mode 100644
index 0000000..0704e7f
--- /dev/null
+++ b/gnss/1.0/service.cpp
@@ -0,0 +1,17 @@
+#define LOG_TAG "android.hardware.gnss@1.0-service"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+ // The GNSS HAL may communicate to other vendor components via
+ // /dev/vndbinder
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ return defaultPassthroughServiceImplementation<IGnss>();
+}