aboutsummaryrefslogtreecommitdiff
path: root/gps
diff options
context:
space:
mode:
Diffstat (limited to 'gps')
-rw-r--r--gps/Android.bp45
-rw-r--r--gps/Android.mk44
-rw-r--r--gps/CleanSpec.mk50
-rw-r--r--gps/Makefile.am10
-rw-r--r--gps/android/1.0/AGnss.cpp203
-rw-r--r--gps/android/1.0/AGnss.h79
-rw-r--r--gps/android/1.0/AGnssRil.cpp115
-rw-r--r--gps/android/1.0/AGnssRil.h83
-rw-r--r--gps/android/1.0/Android.mk99
-rw-r--r--gps/android/1.0/Gnss.cpp346
-rw-r--r--gps/android/1.0/Gnss.h143
-rw-r--r--gps/android/1.0/GnssBatching.cpp130
-rw-r--r--gps/android/1.0/GnssBatching.h80
-rw-r--r--gps/android/1.0/GnssConfiguration.cpp225
-rw-r--r--gps/android/1.0/GnssConfiguration.h71
-rw-r--r--gps/android/1.0/GnssDebug.cpp173
-rw-r--r--gps/android/1.0/GnssDebug.h59
-rw-r--r--gps/android/1.0/GnssGeofencing.cpp141
-rw-r--r--gps/android/1.0/GnssGeofencing.h91
-rw-r--r--gps/android/1.0/GnssMeasurement.cpp101
-rw-r--r--gps/android/1.0/GnssMeasurement.h77
-rw-r--r--gps/android/1.0/GnssNi.cpp85
-rw-r--r--gps/android/1.0/GnssNi.h75
-rw-r--r--gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc4
-rw-r--r--gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml35
-rw-r--r--gps/android/1.0/location_api/BatchingAPIClient.cpp197
-rw-r--r--gps/android/1.0/location_api/BatchingAPIClient.h75
-rw-r--r--gps/android/1.0/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/1.0/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/1.0/location_api/GnssAPIClient.cpp565
-rw-r--r--gps/android/1.0/location_api/GnssAPIClient.h110
-rw-r--r--gps/android/1.0/location_api/LocationUtil.cpp274
-rw-r--r--gps/android/1.0/location_api/LocationUtil.h57
-rw-r--r--gps/android/1.0/location_api/MeasurementAPIClient.cpp276
-rw-r--r--gps/android/1.0/location_api/MeasurementAPIClient.h78
-rw-r--r--gps/android/1.0/service.cpp85
-rw-r--r--gps/android/1.1/AGnss.cpp203
-rw-r--r--gps/android/1.1/AGnss.h79
-rw-r--r--gps/android/1.1/AGnssRil.cpp115
-rw-r--r--gps/android/1.1/AGnssRil.h83
-rw-r--r--gps/android/1.1/Android.mk101
-rw-r--r--gps/android/1.1/Gnss.cpp466
-rw-r--r--gps/android/1.1/Gnss.h154
-rw-r--r--gps/android/1.1/GnssBatching.cpp130
-rw-r--r--gps/android/1.1/GnssBatching.h80
-rw-r--r--gps/android/1.1/GnssConfiguration.cpp308
-rw-r--r--gps/android/1.1/GnssConfiguration.h78
-rw-r--r--gps/android/1.1/GnssDebug.cpp175
-rw-r--r--gps/android/1.1/GnssDebug.h59
-rw-r--r--gps/android/1.1/GnssGeofencing.cpp141
-rw-r--r--gps/android/1.1/GnssGeofencing.h91
-rw-r--r--gps/android/1.1/GnssMeasurement.cpp134
-rw-r--r--gps/android/1.1/GnssMeasurement.h83
-rw-r--r--gps/android/1.1/GnssNi.cpp85
-rw-r--r--gps/android/1.1/GnssNi.h75
-rw-r--r--gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc4
-rw-r--r--gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml35
-rw-r--r--gps/android/1.1/location_api/BatchingAPIClient.cpp197
-rw-r--r--gps/android/1.1/location_api/BatchingAPIClient.h75
-rw-r--r--gps/android/1.1/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/1.1/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/1.1/location_api/GnssAPIClient.cpp565
-rw-r--r--gps/android/1.1/location_api/GnssAPIClient.h110
-rw-r--r--gps/android/1.1/location_api/LocationUtil.cpp274
-rw-r--r--gps/android/1.1/location_api/LocationUtil.h57
-rw-r--r--gps/android/1.1/location_api/MeasurementAPIClient.cpp332
-rw-r--r--gps/android/1.1/location_api/MeasurementAPIClient.h85
-rw-r--r--gps/android/1.1/service.cpp85
-rw-r--r--gps/android/2.0/AGnss.cpp209
-rw-r--r--gps/android/2.0/AGnss.h77
-rw-r--r--gps/android/2.0/AGnssRil.cpp135
-rw-r--r--gps/android/2.0/AGnssRil.h84
-rw-r--r--gps/android/2.0/Android.mk112
-rw-r--r--gps/android/2.0/Gnss.cpp677
-rw-r--r--gps/android/2.0/Gnss.h187
-rw-r--r--gps/android/2.0/GnssBatching.cpp163
-rw-r--r--gps/android/2.0/GnssBatching.h84
-rw-r--r--gps/android/2.0/GnssConfiguration.cpp317
-rw-r--r--gps/android/2.0/GnssConfiguration.h80
-rw-r--r--gps/android/2.0/GnssDebug.cpp299
-rw-r--r--gps/android/2.0/GnssDebug.h62
-rw-r--r--gps/android/2.0/GnssGeofencing.cpp141
-rw-r--r--gps/android/2.0/GnssGeofencing.h91
-rw-r--r--gps/android/2.0/GnssMeasurement.cpp175
-rw-r--r--gps/android/2.0/GnssMeasurement.h87
-rw-r--r--gps/android/2.0/GnssNi.cpp85
-rw-r--r--gps/android/2.0/GnssNi.h75
-rw-r--r--gps/android/2.0/GnssVisibilityControl.cpp169
-rw-r--r--gps/android/2.0/GnssVisibilityControl.h90
-rw-r--r--gps/android/2.0/MeasurementCorrections.cpp73
-rw-r--r--gps/android/2.0/MeasurementCorrections.h77
-rw-r--r--gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc4
-rw-r--r--gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml36
-rw-r--r--gps/android/2.0/location_api/BatchingAPIClient.cpp251
-rw-r--r--gps/android/2.0/location_api/BatchingAPIClient.h82
-rw-r--r--gps/android/2.0/location_api/GeofenceAPIClient.cpp275
-rw-r--r--gps/android/2.0/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/2.0/location_api/GnssAPIClient.cpp728
-rw-r--r--gps/android/2.0/location_api/GnssAPIClient.h115
-rw-r--r--gps/android/2.0/location_api/LocationUtil.cpp334
-rw-r--r--gps/android/2.0/location_api/LocationUtil.h60
-rw-r--r--gps/android/2.0/location_api/MeasurementAPIClient.cpp507
-rw-r--r--gps/android/2.0/location_api/MeasurementAPIClient.h90
-rw-r--r--gps/android/2.0/service.cpp81
-rw-r--r--gps/android/2.1/AGnss.cpp209
-rw-r--r--gps/android/2.1/AGnss.h78
-rw-r--r--gps/android/2.1/AGnssRil.cpp135
-rw-r--r--gps/android/2.1/AGnssRil.h84
-rw-r--r--gps/android/2.1/Android.mk116
-rw-r--r--gps/android/2.1/Gnss.cpp800
-rw-r--r--gps/android/2.1/Gnss.h193
-rw-r--r--gps/android/2.1/GnssAntennaInfo.cpp202
-rw-r--r--gps/android/2.1/GnssAntennaInfo.h90
-rw-r--r--gps/android/2.1/GnssBatching.cpp163
-rw-r--r--gps/android/2.1/GnssBatching.h84
-rw-r--r--gps/android/2.1/GnssConfiguration.cpp408
-rw-r--r--gps/android/2.1/GnssConfiguration.h88
-rw-r--r--gps/android/2.1/GnssDebug.cpp299
-rw-r--r--gps/android/2.1/GnssDebug.h62
-rw-r--r--gps/android/2.1/GnssGeofencing.cpp141
-rw-r--r--gps/android/2.1/GnssGeofencing.h91
-rw-r--r--gps/android/2.1/GnssMeasurement.cpp211
-rw-r--r--gps/android/2.1/GnssMeasurement.h93
-rw-r--r--gps/android/2.1/GnssNi.cpp85
-rw-r--r--gps/android/2.1/GnssNi.h75
-rw-r--r--gps/android/2.1/GnssVisibilityControl.cpp169
-rw-r--r--gps/android/2.1/GnssVisibilityControl.h90
-rw-r--r--gps/android/2.1/MeasurementCorrections.cpp199
-rw-r--r--gps/android/2.1/MeasurementCorrections.h106
-rw-r--r--gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc4
-rwxr-xr-xgps/android/2.1/android.hardware.gnss@2.1-service-qti.xml36
-rw-r--r--gps/android/2.1/location_api/BatchingAPIClient.cpp251
-rwxr-xr-xgps/android/2.1/location_api/BatchingAPIClient.h82
-rwxr-xr-xgps/android/2.1/location_api/GeofenceAPIClient.cpp275
-rwxr-xr-xgps/android/2.1/location_api/GeofenceAPIClient.h77
-rw-r--r--gps/android/2.1/location_api/GnssAPIClient.cpp864
-rwxr-xr-xgps/android/2.1/location_api/GnssAPIClient.h118
-rw-r--r--gps/android/2.1/location_api/LocationUtil.cpp405
-rw-r--r--gps/android/2.1/location_api/LocationUtil.h68
-rw-r--r--gps/android/2.1/location_api/MeasurementAPIClient.cpp642
-rw-r--r--gps/android/2.1/location_api/MeasurementAPIClient.h96
-rwxr-xr-xgps/android/2.1/service.cpp81
-rw-r--r--gps/android/Android.mk2
-rw-r--r--gps/android/utils/Android.bp37
-rw-r--r--gps/android/utils/battery_listener.cpp280
-rw-r--r--gps/android/utils/battery_listener.h32
-rw-r--r--gps/batching/Android.bp31
-rw-r--r--gps/batching/BatchingAdapter.cpp1045
-rw-r--r--gps/batching/BatchingAdapter.h152
-rw-r--r--gps/batching/Makefile.am44
-rw-r--r--gps/batching/configure.ac74
-rw-r--r--gps/batching/location-batching.pc.in10
-rw-r--r--gps/batching/location_batching.cpp134
-rw-r--r--gps/configure.ac87
-rw-r--r--gps/core/Android.bp56
-rw-r--r--gps/core/ContextBase.cpp384
-rw-r--r--gps/core/ContextBase.h385
-rw-r--r--gps/core/EngineHubProxyBase.h160
-rw-r--r--gps/core/LBSProxyBase.h70
-rw-r--r--gps/core/LocAdapterBase.cpp439
-rw-r--r--gps/core/LocAdapterBase.h246
-rw-r--r--gps/core/LocAdapterProxyBase.h77
-rw-r--r--gps/core/LocApiBase.cpp1069
-rw-r--r--gps/core/LocApiBase.h375
-rw-r--r--gps/core/LocContext.cpp87
-rw-r--r--gps/core/LocContext.h60
-rw-r--r--gps/core/Makefile.am74
-rw-r--r--gps/core/SystemStatus.cpp1760
-rw-r--r--gps/core/SystemStatus.h924
-rw-r--r--gps/core/SystemStatusOsObserver.cpp592
-rw-r--r--gps/core/SystemStatusOsObserver.h181
-rw-r--r--gps/core/configure.ac107
-rw-r--r--gps/core/data-items/DataItemConcreteTypesBase.h555
-rw-r--r--gps/core/data-items/DataItemId.h79
-rw-r--r--gps/core/data-items/DataItemsFactoryProxy.cpp82
-rw-r--r--gps/core/data-items/DataItemsFactoryProxy.h55
-rw-r--r--gps/core/data-items/IDataItemCore.h82
-rw-r--r--gps/core/loc-core.pc.in10
-rw-r--r--gps/core/loc_core_log.cpp215
-rw-r--r--gps/core/loc_core_log.h58
-rw-r--r--gps/core/observer/IDataItemObserver.h76
-rw-r--r--gps/core/observer/IDataItemSubscription.h129
-rw-r--r--gps/core/observer/IFrameworkActionReq.h104
-rw-r--r--gps/core/observer/IOsObserver.h107
-rw-r--r--gps/etc/Android.bp55
-rw-r--r--gps/etc/apdr.conf183
-rw-r--r--gps/etc/flp.conf60
-rw-r--r--gps/etc/gnss_antenna_info.conf134
-rw-r--r--gps/etc/gps.conf391
-rw-r--r--gps/etc/izat.conf277
-rw-r--r--gps/etc/lowi.conf26
-rw-r--r--gps/etc/sap.conf181
-rw-r--r--gps/etc/seccomp_policy/gnss@2.0-base.policy95
-rw-r--r--gps/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy48
-rw-r--r--gps/geofence/Android.bp31
-rw-r--r--gps/geofence/GeofenceAdapter.cpp866
-rw-r--r--gps/geofence/GeofenceAdapter.h136
-rw-r--r--gps/geofence/Makefile.am50
-rw-r--r--gps/geofence/configure.ac72
-rw-r--r--gps/geofence/location-geofence.pc.in10
-rw-r--r--gps/geofence/location_geofence.cpp145
-rw-r--r--gps/gnss/Agps.cpp675
-rw-r--r--gps/gnss/Agps.h318
-rw-r--r--gps/gnss/Android.bp35
-rw-r--r--gps/gnss/GnssAdapter.cpp6916
-rw-r--r--gps/gnss/GnssAdapter.h648
-rw-r--r--gps/gnss/Makefile.am32
-rw-r--r--gps/gnss/NativeAgpsHandler.cpp127
-rw-r--r--gps/gnss/NativeAgpsHandler.h64
-rw-r--r--gps/gnss/XtraSystemStatusObserver.cpp384
-rw-r--r--gps/gnss/XtraSystemStatusObserver.h112
-rw-r--r--gps/gnss/location_gnss.cpp593
-rw-r--r--gps/gps_vendor_board.mk7
-rw-r--r--gps/gps_vendor_product.mk44
-rw-r--r--gps/loc-hal.pc.in10
-rw-r--r--gps/location/Android.bp36
-rw-r--r--gps/location/ILocationAPI.h406
-rw-r--r--gps/location/LocationAPI.cpp976
-rw-r--r--gps/location/LocationAPI.h512
-rw-r--r--gps/location/LocationAPIClientBase.cpp977
-rw-r--r--gps/location/LocationAPIClientBase.h592
-rw-r--r--gps/location/LocationDataTypes.h2070
-rw-r--r--gps/location/Makefile.am44
-rw-r--r--gps/location/configure.ac95
-rw-r--r--gps/location/location-api.pc.in10
-rw-r--r--gps/location/location_interface.h144
-rw-r--r--gps/pla/Android.bp7
-rw-r--r--gps/pla/android/loc_pla.h97
-rw-r--r--gps/pla/oe/loc_pla.h175
-rw-r--r--gps/utils/Android.bp54
-rw-r--r--gps/utils/LocHeap.cpp280
-rw-r--r--gps/utils/LocHeap.h100
-rw-r--r--gps/utils/LocIpc.cpp430
-rw-r--r--gps/utils/LocIpc.h241
-rw-r--r--gps/utils/LocLoggerBase.h39
-rw-r--r--gps/utils/LocSharedLock.h81
-rw-r--r--gps/utils/LocThread.cpp111
-rw-r--r--gps/utils/LocThread.h95
-rw-r--r--gps/utils/LocTimer.cpp648
-rw-r--r--gps/utils/LocTimer.h78
-rw-r--r--gps/utils/LocUnorderedSetMap.h201
-rw-r--r--gps/utils/LogBuffer.cpp189
-rw-r--r--gps/utils/LogBuffer.h95
-rw-r--r--gps/utils/Makefile.am75
-rw-r--r--gps/utils/MsgTask.cpp120
-rw-r--r--gps/utils/MsgTask.h56
-rw-r--r--gps/utils/SkipList.h158
-rw-r--r--gps/utils/configure.ac92
-rw-r--r--gps/utils/gps-utils.pc.in10
-rw-r--r--gps/utils/gps_extended.h114
-rw-r--r--gps/utils/gps_extended_c.h2429
-rw-r--r--gps/utils/linked_list.c325
-rw-r--r--gps/utils/linked_list.h219
-rw-r--r--gps/utils/loc_cfg.cpp1140
-rw-r--r--gps/utils/loc_cfg.h167
-rw-r--r--gps/utils/loc_gps.h2235
-rw-r--r--gps/utils/loc_log.cpp282
-rw-r--r--gps/utils/loc_log.h122
-rw-r--r--gps/utils/loc_misc_utils.cpp351
-rw-r--r--gps/utils/loc_misc_utils.h321
-rw-r--r--gps/utils/loc_nmea.cpp2347
-rw-r--r--gps/utils/loc_nmea.h95
-rw-r--r--gps/utils/loc_target.cpp249
-rw-r--r--gps/utils/loc_target.h82
-rw-r--r--gps/utils/loc_timer.h74
-rw-r--r--gps/utils/log_util.h291
-rw-r--r--gps/utils/msg_q.c380
-rw-r--r--gps/utils/msg_q.h230
268 files changed, 66901 insertions, 0 deletions
diff --git a/gps/Android.bp b/gps/Android.bp
new file mode 100644
index 0000000..ea0d991
--- /dev/null
+++ b/gps/Android.bp
@@ -0,0 +1,45 @@
+GNSS_CFLAGS = [
+ "-Werror",
+ "-Wno-error=unused-parameter",
+ "-Wno-error=macro-redefined",
+ "-Wno-error=reorder",
+ "-Wno-error=missing-braces",
+ "-Wno-error=self-assign",
+ "-Wno-error=enum-conversion",
+ "-Wno-error=logical-op-parentheses",
+ "-Wno-error=null-arithmetic",
+ "-Wno-error=null-conversion",
+ "-Wno-error=parentheses-equality",
+ "-Wno-error=undefined-bool-conversion",
+ "-Wno-error=tautological-compare",
+ "-Wno-error=switch",
+ "-Wno-error=date-time",
+]
+
+/* Activate the following for regression testing */
+GNSS_SANITIZE = {
+/* address: true,*/
+ cfi: true,
+ misc_undefined: [
+ "bounds",
+ "null",
+ "unreachable",
+ "integer",
+ ],
+}
+
+/* Activate the following for debug purposes only,
+ comment out for production */
+GNSS_SANITIZE_DIAG = {
+/*
+ diag: {
+ cfi: true,
+ misc_undefined: [
+ "bounds",
+ "null",
+ "unreachable",
+ "integer",
+ ],
+ },
+*/
+}
diff --git a/gps/Android.mk b/gps/Android.mk
new file mode 100644
index 0000000..77d61c9
--- /dev/null
+++ b/gps/Android.mk
@@ -0,0 +1,44 @@
+ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
+
+# Set required flags
+GNSS_CFLAGS := \
+ -Werror \
+ -Wno-error=unused-parameter \
+ -Wno-error=macro-redefined \
+ -Wno-error=reorder \
+ -Wno-error=missing-braces \
+ -Wno-error=self-assign \
+ -Wno-error=enum-conversion \
+ -Wno-error=logical-op-parentheses \
+ -Wno-error=null-arithmetic \
+ -Wno-error=null-conversion \
+ -Wno-error=parentheses-equality \
+ -Wno-error=undefined-bool-conversion \
+ -Wno-error=tautological-compare \
+ -Wno-error=switch \
+ -Wno-error=date-time
+
+GNSS_HIDL_VERSION = 2.1
+
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8937
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8953
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8998
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += apq8098_latv
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm710
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += qcs605
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm845
+GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += sdm660
+
+ifneq (,$(filter $(GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST),$(TARGET_BOARD_PLATFORM)))
+GNSS_HIDL_LEGACY_MEASURMENTS = true
+endif
+
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+GNSS_SANITIZE := cfi bounds null unreachable integer
+# Activate the following two lines for regression testing
+#GNSS_SANITIZE += address
+#GNSS_SANITIZE_DIAG := $(GNSS_SANITIZE)
+
+endif # ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
diff --git a/gps/CleanSpec.mk b/gps/CleanSpec.mk
new file mode 100644
index 0000000..dd1849d
--- /dev/null
+++ b/gps/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2007 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libloc_api*)
diff --git a/gps/Makefile.am b/gps/Makefile.am
new file mode 100644
index 0000000..cd4a731
--- /dev/null
+++ b/gps/Makefile.am
@@ -0,0 +1,10 @@
+# Makefile.am - Automake script for gps loc_api
+#
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = gnss
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = loc-hal.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/gps/android/1.0/AGnss.cpp b/gps/android/1.0/AGnss.cpp
new file mode 100644
index 0000000..79f665c
--- /dev/null
+++ b/gps/android/1.0/AGnss.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status){
+ if (nullptr != spAGnss) {
+ spAGnss->statusIpV4Cb(status);
+ }
+}
+
+void AGnss::statusIpV4Cb(AGnssExtStatusIpV4 status) {
+ IAGnssCallback::AGnssStatusIpV4 st = {};
+
+ switch (status.type) {
+ case LOC_AGPS_TYPE_SUPL:
+ st.type = IAGnssCallback::AGnssType::TYPE_SUPL;
+ break;
+ case LOC_AGPS_TYPE_C2K:
+ st.type = IAGnssCallback::AGnssType::TYPE_C2K;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", status.type);
+ return;
+ }
+
+ switch (status.status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status.status);
+ return;
+ }
+ st.ipV4Addr = status.ipV4Addr;
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusIpV4Cb(st);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::TYPE_SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::TYPE_C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<int>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/AGnss.h b/gps/android/1.0/AGnss.h
new file mode 100644
index 0000000..cdd5931
--- /dev/null
+++ b/gps/android/1.0/AGnss.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
+
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H
diff --git a/gps/android/1.0/AGnssRil.cpp b/gps/android/1.0/AGnssRil.cpp
new file mode 100644
index 0000000..d7f30eb
--- /dev/null
+++ b/gps/android/1.0/AGnssRil.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/AGnssRil.h b/gps/android/1.0/AGnssRil.h
new file mode 100644
index 0000000..7f18c57
--- /dev/null
+++ b/gps/android/1.0/AGnssRil.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, NetworkType type, bool roaming) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
diff --git a/gps/android/1.0/Android.mk b/gps/android/1.0/Android.mk
new file mode 100644
index 0000000..797ecce
--- /dev/null
+++ b/gps/android/1.0/Android.mk
@@ -0,0 +1,99 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssMeasurement.cpp \
+ GnssNi.cpp \
+ GnssConfiguration.cpp \
+ GnssDebug.cpp \
+ AGnssRil.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/LocationUtil.cpp \
+ location_api/GnssAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.0-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@1.0-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/1.0/Gnss.cpp b/gps/android/1.0/Gnss.cpp
new file mode 100644
index 0000000..308cc7c
--- /dev/null
+++ b/gps/android/1.0/Gnss.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+static sp<Gnss> sGnss;
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->stop();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not ");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+ }
+ if (mApi == nullptr) {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ }
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (const GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ mAGnssIface = new AGnss(this);
+ return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNi = new GnssNi(this);
+ return mGnssNi;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssGeofencingIface = new GnssGeofencing();
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ mGnssBatching = new GnssBatching();
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssDebug = new GnssDebug(this);
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ mGnssRil = new AGnssRil(this);
+ return mGnssRil;
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/Gnss.h b/gps/android/1.0/Gnss.h
new file mode 100644
index 0000000..900a510
--- /dev/null
+++ b/gps/android/1.0/Gnss.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <GnssAPIClient.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<AGnss> mAGnssIface = nullptr;
+ sp<GnssNi> mGnssNi = nullptr;
+ sp<GnssMeasurement> mGnssMeasurement = nullptr;
+ sp<GnssConfiguration> mGnssConfig = nullptr;
+ sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<GnssBatching> mGnssBatching = nullptr;
+ sp<IGnssDebug> mGnssDebug = nullptr;
+ sp<AGnssRil> mGnssRil = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSS_H
diff --git a/gps/android/1.0/GnssBatching.cpp b/gps/android/1.0/GnssBatching.cpp
new file mode 100644
index 0000000..f92697f
--- /dev/null
+++ b/gps/android/1.0/GnssBatching.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssBatching.h b/gps/android/1.0/GnssBatching.h
new file mode 100644
index 0000000..8fab857
--- /dev/null
+++ b/gps/android/1.0/GnssBatching.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/gps/android/1.0/GnssConfiguration.cpp b/gps/android/1.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..a7f64fa
--- /dev/null
+++ b/gps/android/1.0/GnssConfiguration.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ config.suplEmergencyServices = (enabled ?
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES :
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssConfiguration.h b/gps/android/1.0/GnssConfiguration.h
new file mode 100644
index 0000000..d0e2ba8
--- /dev/null
+++ b/gps/android/1.0/GnssConfiguration.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H
diff --git a/gps/android/1.0/GnssDebug.cpp b/gps/android/1.0/GnssDebug.cpp
new file mode 100644
index 0000000..ead72e1
--- /dev/null
+++ b/gps/android/1.0/GnssDebug.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0 ||
+ data.time.timeUncertaintyNs > (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ SatelliteData s = { };
+ std::vector<SatelliteData> s_array = { };
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssDebug.h b/gps/android/1.0/GnssDebug.h
new file mode 100644
index 0000000..a7116cb
--- /dev/null
+++ b/gps/android/1.0/GnssDebug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+ * These declarations were generated from IGnssDebug.hal.
+ */
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H
diff --git a/gps/android/1.0/GnssGeofencing.cpp b/gps/android/1.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..4be6d8a
--- /dev/null
+++ b/gps/android/1.0/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGE("%s]: mApi is NOT nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssGeofencing.h b/gps/android/1.0/GnssGeofencing.h
new file mode 100644
index 0000000..db5f9d2
--- /dev/null
+++ b/gps/android/1.0/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H
diff --git a/gps/android/1.0/GnssMeasurement.cpp b/gps/android/1.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..7af9e27
--- /dev/null
+++ b/gps/android/1.0/GnssMeasurement.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include <MeasurementAPIClient.h>
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+
+Return<IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ mApi->measurementClose();
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssMeasurement.h b/gps/android/1.0/GnssMeasurement.h
new file mode 100644
index 0000000..4247dbf
--- /dev/null
+++ b/gps/android/1.0/GnssMeasurement.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ MeasurementAPIClient* mApi;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H
diff --git a/gps/android/1.0/GnssNi.cpp b/gps/android/1.0/GnssNi.cpp
new file mode 100644
index 0000000..d06cc20
--- /dev/null
+++ b/gps/android/1.0/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/GnssNi.h b/gps/android/1.0/GnssNi.h
new file mode 100644
index 0000000..90f62d5
--- /dev/null
+++ b/gps/android/1.0/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H
diff --git a/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc
new file mode 100644
index 0000000..1fbd893
--- /dev/null
+++ b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml
new file mode 100644
index 0000000..46bcffb
--- /dev/null
+++ b/gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml
@@ -0,0 +1,35 @@
+<!-- Copyright (c) 2019, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.0::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/1.0/location_api/BatchingAPIClient.cpp b/gps/android/1.0/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..94a234d
--- /dev/null
+++ b/gps/android/1.0/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,197 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(callback),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ if (mGnssBatchingCbIface != nullptr) {
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ }
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::stopSession()
+{
+ LOC_LOGD("%s]: ", __FUNCTION__);
+ int retVal = -1;
+ if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+void BatchingAPIClient::getBatchedLocation(int last_n_locations)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations);
+ locAPIGetBatchedLocations(mDefaultId, last_n_locations);
+}
+
+void BatchingAPIClient::flushBatchedLocations()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+}
+
+void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+}
+
+void BatchingAPIClient::onBatchingCb(size_t count, Location* location,
+ BatchingOptions /*batchOptions*/)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (mGnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/BatchingAPIClient.h b/gps/android/1.0/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..c3b0a7b
--- /dev/null
+++ b/gps/android/1.0/location_api/BatchingAPIClient.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+ int getBatchSize();
+ int startSession(const V1_0::IGnssBatching::Options& options);
+ int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
+ int stopSession();
+ void getBatchedLocation(int last_n_locations);
+ void flushBatchedLocations();
+
+ inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; }
+
+ // callbacks
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
+
+private:
+ ~BatchingAPIClient();
+
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.cpp b/gps/android/1.0/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..774a049
--- /dev/null
+++ b/gps/android/1.0/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssGeofencingCbIface(callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+
+ locationCallbacks.geofenceBreachCb = nullptr;
+ if (mGnssGeofencingCbIface != nullptr) {
+ locationCallbacks.geofenceBreachCb =
+ [this](GeofenceBreachNotification geofenceBreachNotification) {
+ onGeofenceBreachCb(geofenceBreachNotification);
+ };
+
+ locationCallbacks.geofenceStatusCb =
+ [this](GeofenceStatusNotification geofenceStatusNotification) {
+ onGeofenceStatusCb(geofenceStatusNotification);
+ };
+ }
+
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
+{
+ LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
+ geofence_id, latitude, longitude, radius_meters,
+ last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
+
+ GeofenceOption options;
+ memset(&options, 0, sizeof(GeofenceOption));
+ options.size = sizeof(GeofenceOption);
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT;
+ options.responsiveness = notification_responsiveness_ms;
+
+ GeofenceInfo data;
+ data.size = sizeof(GeofenceInfo);
+ data.latitude = latitude;
+ data.longitude = longitude;
+ data.radius = radius_meters;
+
+ LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ onAddGeofencesCb(1, &err, &geofence_id);
+ }
+}
+
+void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIPauseGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
+ GeofenceBreachTypeMask mask = 0;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ mask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ mask |= GEOFENCE_BREACH_EXIT_BIT;
+ locAPIResumeGeofences(1, &geofence_id, &mask);
+}
+
+void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIRemoveGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceRemoveAll()
+{
+ LOC_LOGD("%s]", __FUNCTION__);
+ // TODO locAPIRemoveAllGeofences();
+}
+
+// callbacks
+void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp));
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
+ if (mGnssGeofencingCbIface != nullptr) {
+ IGnssGeofenceCallback::GeofenceAvailability status =
+ IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
+ if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
+ status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
+ }
+ GnssLocation gnssLocation;
+ memset(&gnssLocation, 0, sizeof(GnssLocation));
+ auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.h b/gps/android/1.0/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..b6a009b
--- /dev/null
+++ b/gps/android/1.0/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+ GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
+
+ void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms);
+ void geofencePause(uint32_t geofence_id);
+ void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions);
+ void geofenceRemove(uint32_t geofence_id);
+ void geofenceRemoveAll();
+
+ // callbacks
+ void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final;
+ void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final;
+ void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+
+private:
+ virtual ~GeofenceAPIClient() = default;
+
+ sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/1.0/location_api/GnssAPIClient.cpp b/gps/android/1.0/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..4247258
--- /dev/null
+++ b/gps/android/1.0/location_api/GnssAPIClient.cpp
@@ -0,0 +1,565 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnss;
+using ::android::hardware::gnss::V1_0::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
+
+GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+ }
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+
+ locationCallbacks.gnssNiCb = nullptr;
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
+ onGnssNiCb(id, gnssNiNotification);
+ };
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+ }
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+ }
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
+ GnssNiResponse data;
+ switch (userResponse) {
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
+ data = GNSS_NI_RESPONSE_ACCEPT;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
+ data = GNSS_NI_RESPONSE_DENY;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
+ data = GNSS_NI_RESPONSE_NO_RESPONSE;
+ break;
+ default:
+ data = GNSS_NI_RESPONSE_IGNORE;
+ break;
+ }
+
+ locAPIGnssNiResponse(notifId, data);
+}
+
+// these apis using LocationAPIControlClient
+void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
+{
+ LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ GnssAidingData data;
+ memset(&data, 0, sizeof (GnssAidingData));
+ data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+ auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+ gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
+ __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT);
+ out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.numSvs; i++) {
+ IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
+ convertGnssSvid(in.gnssSvs[i], info.svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
+ info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ info.elevationDegrees = in.gnssSvs[i].elevation;
+ info.azimuthDegrees = in.gnssSvs[i].azimuth;
+ info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/GnssAPIClient.h b/gps/android/1.0/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..427b0db
--- /dev/null
+++ b/gps/android/1.0/location_api/GnssAPIClient.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/1.0/IGnssCallback.h>
+#include <android/hardware/gnss/1.0/IGnssNiCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+ GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ GnssAPIClient(const GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/1.0/location_api/LocationUtil.cpp b/gps/android/1.0/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..870a8aa
--- /dev/null
+++ b/gps/android/1.0/location_api/LocationUtil.cpp
@@ -0,0 +1,274 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+
+void convertGnssLocation(Location& in, GnssLocation& out)
+{
+ memset(&out, 0, sizeof(GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(const GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch(in.type){
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/LocationUtil.h b/gps/android/1.0/location_api/LocationUtil.h
new file mode 100644
index 0000000..f6760e5
--- /dev/null
+++ b/gps/android/1.0/location_api/LocationUtil.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/1.0/types.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.cpp b/gps/android/1.0/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..9b23308
--- /dev/null
+++ b/gps/android/1.0/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,276 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+ if (mGnssMeasurementCbIface != nullptr) {
+ locationCallbacks.gnssMeasurementsCb =
+ [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+ onGnssMeasurementsCb(gnssMeasurementsNotification);
+ };
+ }
+
+ locAPISetCallbacks(locationCallbacks);
+
+ TrackingOptions options = {};
+ memset(&options, 0, sizeof(TrackingOptions));
+ options.size = sizeof(TrackingOptions);
+ options.minInterval = 1000;
+ options.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ mTracking = true;
+ LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+ locAPIStartTracking(options);
+ return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ mTracking = false;
+ locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+ GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+ LOC_LOGD("%s]: (count: %zu active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface != nullptr) {
+ V1_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+ memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
+ out.multipathIndicator =
+ static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+ out.snrDb = in.signalToNoiseRatioDb;
+ out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
+ __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT);
+ out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.measurementCount; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i]);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.h b/gps/android/1.0/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..225deac
--- /dev/null
+++ b/gps/android/1.0/location_api/MeasurementAPIClient.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.0/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking();
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+
+ bool mTracking;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/1.0/service.cpp b/gps/android/1.0/service.cpp
new file mode 100644
index 0000000..2a6f60f
--- /dev/null
+++ b/gps/android/1.0/service.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@1.0-service-qti"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V1_0::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ if (vendorEnhanced) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGE("LOC_HIDL_VERSION not defined.");
+ #endif
+ }
+
+ joinRpcThreadpool();
+
+ } else {
+ ALOGE("Error while registering IGnss 1.0 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/1.1/AGnss.cpp b/gps/android/1.1/AGnss.cpp
new file mode 100644
index 0000000..d8f9706
--- /dev/null
+++ b/gps/android/1.1/AGnss.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status){
+ if (nullptr != spAGnss) {
+ spAGnss->statusIpV4Cb(status);
+ }
+}
+
+void AGnss::statusIpV4Cb(AGnssExtStatusIpV4 status) {
+ IAGnssCallback::AGnssStatusIpV4 st = {};
+
+ switch (status.type) {
+ case LOC_AGPS_TYPE_SUPL:
+ st.type = IAGnssCallback::AGnssType::TYPE_SUPL;
+ break;
+ case LOC_AGPS_TYPE_C2K:
+ st.type = IAGnssCallback::AGnssType::TYPE_C2K;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", status.type);
+ return;
+ }
+
+ switch (status.status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ st.status = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status.status);
+ return;
+ }
+ st.ipV4Addr = status.ipV4Addr;
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusIpV4Cb(st);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::TYPE_SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::TYPE_C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<int>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/AGnss.h b/gps/android/1.1/AGnss.h
new file mode 100644
index 0000000..4b599b9
--- /dev/null
+++ b/gps/android/1.1/AGnss.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
+
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(const hidl_string& apn,
+ IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_AGNSS_H
diff --git a/gps/android/1.1/AGnssRil.cpp b/gps/android/1.1/AGnssRil.cpp
new file mode 100644
index 0000000..95c8d63
--- /dev/null
+++ b/gps/android/1.1/AGnssRil.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/AGnssRil.h b/gps/android/1.1/AGnssRil.h
new file mode 100644
index 0000000..5c9298a
--- /dev/null
+++ b/gps/android/1.1/AGnssRil.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, NetworkType type, bool roaming) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_
diff --git a/gps/android/1.1/Android.mk b/gps/android/1.1/Android.mk
new file mode 100644
index 0000000..66abd06
--- /dev/null
+++ b/gps/android/1.1/Android.mk
@@ -0,0 +1,101 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.1-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssMeasurement.cpp \
+ GnssNi.cpp \
+ GnssConfiguration.cpp \
+ GnssDebug.cpp \
+ AGnssRil.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/LocationUtil.cpp \
+ location_api/GnssAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.1-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.1-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@1.1-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/1.1/Gnss.cpp b/gps/android/1.1/Gnss.cpp
new file mode 100644
index 0000000..537f6a6
--- /dev/null
+++ b/gps/android/1.1/Gnss.cpp
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->stop();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+ }
+ if (mApi == nullptr) {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ }
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (const GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ mAGnssIface = new AGnss(this);
+ return mAGnssIface;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNi = new GnssNi(this);
+ return mGnssNi;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssGeofencingIface = new GnssGeofencing();
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ mGnssBatching = new GnssBatching();
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ mGnssDebug = new GnssDebug(this);
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ mGnssRil = new AGnssRil(this);
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ callback->gnssNameCb(getVersionString());
+ mGnssCbIface_1_1 = callback;
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+ return setCallback(callback);
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/Gnss.h b/gps/android/1.1/Gnss.h
new file mode 100644
index 0000000..15645eb
--- /dev/null
+++ b/gps/android/1.1/Gnss.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017-2018-2018-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <GnssAPIClient.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<AGnss> mAGnssIface = nullptr;
+ sp<GnssNi> mGnssNi = nullptr;
+ sp<GnssMeasurement> mGnssMeasurement = nullptr;
+ sp<GnssConfiguration> mGnssConfig = nullptr;
+ sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<GnssBatching> mGnssBatching = nullptr;
+ sp<IGnssDebug> mGnssDebug = nullptr;
+ sp<AGnssRil> mGnssRil = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSS_H
diff --git a/gps/android/1.1/GnssBatching.cpp b/gps/android/1.1/GnssBatching.cpp
new file mode 100644
index 0000000..8ab264d
--- /dev/null
+++ b/gps/android/1.1/GnssBatching.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssBatching.h b/gps/android/1.1/GnssBatching.h
new file mode 100644
index 0000000..8e235d8
--- /dev/null
+++ b/gps/android/1.1/GnssBatching.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSBATCHING_H
diff --git a/gps/android/1.1/GnssConfiguration.cpp b/gps/android/1.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..ad255d1
--- /dev/null
+++ b/gps/android/1.1/GnssConfiguration.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ config.suplEmergencyServices = (enabled ?
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES :
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %d", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssConfiguration.h b/gps/android/1.1/GnssConfiguration.h
new file mode 100644
index 0000000..daea159
--- /dev/null
+++ b/gps/android/1.1/GnssConfiguration.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/1.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSCONFIGURATION_H
diff --git a/gps/android/1.1/GnssDebug.cpp b/gps/android/1.1/GnssDebug.cpp
new file mode 100644
index 0000000..f164c54
--- /dev/null
+++ b/gps/android/1.1/GnssDebug.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ SatelliteData s = { };
+ std::vector<SatelliteData> s_array = { };
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssDebug.h b/gps/android/1.1/GnssDebug.h
new file mode 100644
index 0000000..cb818ac
--- /dev/null
+++ b/gps/android/1.1/GnssDebug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+ * These declarations were generated from IGnssDebug.hal.
+ */
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H
diff --git a/gps/android/1.1/GnssGeofencing.cpp b/gps/android/1.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..a4aaf88
--- /dev/null
+++ b/gps/android/1.1/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssGeofencing.h b/gps/android/1.1/GnssGeofencing.h
new file mode 100644
index 0000000..94a73de
--- /dev/null
+++ b/gps/android/1.1/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSGEOFENCING_H
diff --git a/gps/android/1.1/GnssMeasurement.cpp b/gps/android/1.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..6f8c14d
--- /dev/null
+++ b/gps/android/1.1/GnssMeasurement.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include <MeasurementAPIClient.h>
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+
+Return<IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<IGnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssMeasurement.h b/gps/android/1.1/GnssMeasurement.h
new file mode 100644
index 0000000..373f0d0
--- /dev/null
+++ b/gps/android/1.1/GnssMeasurement.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_1::IGnssMeasurement;
+using ::android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ MeasurementAPIClient* mApi;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSMEASUREMENT_H
diff --git a/gps/android/1.1/GnssNi.cpp b/gps/android/1.1/GnssNi.cpp
new file mode 100644
index 0000000..5ce9569
--- /dev/null
+++ b/gps/android/1.1/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/GnssNi.h b/gps/android/1.1/GnssNi.h
new file mode 100644
index 0000000..6733e5b
--- /dev/null
+++ b/gps/android/1.1/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSNI_H
diff --git a/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc
new file mode 100644
index 0000000..bd65584
--- /dev/null
+++ b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@1.1-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml
new file mode 100644
index 0000000..c9c83fb
--- /dev/null
+++ b/gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml
@@ -0,0 +1,35 @@
+<!-- Copyright (c) 2019, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/1.1/location_api/BatchingAPIClient.cpp b/gps/android/1.1/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..6ec27a9
--- /dev/null
+++ b/gps/android/1.1/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,197 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(callback),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ if (mGnssBatchingCbIface != nullptr) {
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ }
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::stopSession()
+{
+ LOC_LOGD("%s]: ", __FUNCTION__);
+ int retVal = -1;
+ if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+void BatchingAPIClient::getBatchedLocation(int last_n_locations)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations);
+ locAPIGetBatchedLocations(mDefaultId, last_n_locations);
+}
+
+void BatchingAPIClient::flushBatchedLocations()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+}
+
+void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+}
+
+void BatchingAPIClient::onBatchingCb(size_t count, Location* location,
+ BatchingOptions /*batchOptions*/)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (mGnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/BatchingAPIClient.h b/gps/android/1.1/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..4c90626
--- /dev/null
+++ b/gps/android/1.1/location_api/BatchingAPIClient.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+ int getBatchSize();
+ int startSession(const V1_0::IGnssBatching::Options& options);
+ int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
+ int stopSession();
+ void getBatchedLocation(int last_n_locations);
+ void flushBatchedLocations();
+
+ inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; }
+
+ // callbacks
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
+
+private:
+ ~BatchingAPIClient();
+
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/1.1/location_api/GeofenceAPIClient.cpp b/gps/android/1.1/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..93d175e
--- /dev/null
+++ b/gps/android/1.1/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssGeofencingCbIface(callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+
+ locationCallbacks.geofenceBreachCb = nullptr;
+ if (mGnssGeofencingCbIface != nullptr) {
+ locationCallbacks.geofenceBreachCb =
+ [this](GeofenceBreachNotification geofenceBreachNotification) {
+ onGeofenceBreachCb(geofenceBreachNotification);
+ };
+
+ locationCallbacks.geofenceStatusCb =
+ [this](GeofenceStatusNotification geofenceStatusNotification) {
+ onGeofenceStatusCb(geofenceStatusNotification);
+ };
+ }
+
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
+{
+ LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
+ geofence_id, latitude, longitude, radius_meters,
+ last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
+
+ GeofenceOption options;
+ memset(&options, 0, sizeof(GeofenceOption));
+ options.size = sizeof(GeofenceOption);
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT;
+ options.responsiveness = notification_responsiveness_ms;
+
+ GeofenceInfo data;
+ data.size = sizeof(GeofenceInfo);
+ data.latitude = latitude;
+ data.longitude = longitude;
+ data.radius = radius_meters;
+
+ LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ onAddGeofencesCb(1, &err, &geofence_id);
+ }
+}
+
+void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIPauseGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
+ GeofenceBreachTypeMask mask = 0;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ mask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ mask |= GEOFENCE_BREACH_EXIT_BIT;
+ locAPIResumeGeofences(1, &geofence_id, &mask);
+}
+
+void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIRemoveGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceRemoveAll()
+{
+ LOC_LOGD("%s]", __FUNCTION__);
+ // TODO locAPIRemoveAllGeofences();
+}
+
+// callbacks
+void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp));
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
+ if (mGnssGeofencingCbIface != nullptr) {
+ IGnssGeofenceCallback::GeofenceAvailability status =
+ IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
+ if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
+ status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
+ }
+ GnssLocation gnssLocation;
+ memset(&gnssLocation, 0, sizeof(GnssLocation));
+ auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/GeofenceAPIClient.h b/gps/android/1.1/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..0ffff91
--- /dev/null
+++ b/gps/android/1.1/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+ GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
+
+ void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms);
+ void geofencePause(uint32_t geofence_id);
+ void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions);
+ void geofenceRemove(uint32_t geofence_id);
+ void geofenceRemoveAll();
+
+ // callbacks
+ void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final;
+ void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final;
+ void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+
+private:
+ virtual ~GeofenceAPIClient() = default;
+
+ sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/1.1/location_api/GnssAPIClient.cpp b/gps/android/1.1/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..a2c4eec
--- /dev/null
+++ b/gps/android/1.1/location_api/GnssAPIClient.cpp
@@ -0,0 +1,565 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnss;
+using ::android::hardware::gnss::V1_0::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
+
+GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+ }
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+
+ locationCallbacks.gnssNiCb = nullptr;
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
+ onGnssNiCb(id, gnssNiNotification);
+ };
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+ }
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ if (mGnssCbIface != nullptr) {
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+ }
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
+ GnssNiResponse data;
+ switch (userResponse) {
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
+ data = GNSS_NI_RESPONSE_ACCEPT;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
+ data = GNSS_NI_RESPONSE_DENY;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
+ data = GNSS_NI_RESPONSE_NO_RESPONSE;
+ break;
+ default:
+ data = GNSS_NI_RESPONSE_IGNORE;
+ break;
+ }
+
+ locAPIGnssNiResponse(notifId, data);
+}
+
+// these apis using LocationAPIControlClient
+void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
+{
+ LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ GnssAidingData data;
+ memset(&data, 0, sizeof (GnssAidingData));
+ data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+ auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__,
+ gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
+ __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT);
+ out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.numSvs; i++) {
+ IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
+ convertGnssSvid(in.gnssSvs[i], info.svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
+ info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ info.elevationDegrees = in.gnssSvs[i].elevation;
+ info.azimuthDegrees = in.gnssSvs[i].azimuth;
+ info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/GnssAPIClient.h b/gps/android/1.1/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..3829265
--- /dev/null
+++ b/gps/android/1.1/location_api/GnssAPIClient.h
@@ -0,0 +1,110 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <android/hardware/gnss/1.1/IGnssCallback.h>
+#include <android/hardware/gnss/1.0/IGnssNiCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+ GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ GnssAPIClient(const GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/1.1/location_api/LocationUtil.cpp b/gps/android/1.1/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..26fd920
--- /dev/null
+++ b/gps/android/1.1/location_api/LocationUtil.cpp
@@ -0,0 +1,274 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+
+void convertGnssLocation(Location& in, GnssLocation& out)
+{
+ memset(&out, 0, sizeof(GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(const GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch(in.type){
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { //OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/LocationUtil.h b/gps/android/1.1/location_api/LocationUtil.h
new file mode 100644
index 0000000..af3c93f
--- /dev/null
+++ b/gps/android/1.1/location_api/LocationUtil.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/1.0/types.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/1.1/location_api/MeasurementAPIClient.cpp b/gps/android/1.1/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..a87ae6d
--- /dev/null
+++ b/gps/android/1.1/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,332 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mGnssMeasurementCbIface_1_1(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ mGnssMeasurementCbIface_1_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking(
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+ if (mGnssMeasurementCbIface_1_1 != nullptr || mGnssMeasurementCbIface != nullptr) {
+ locationCallbacks.gnssMeasurementsCb =
+ [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+ onGnssMeasurementsCb(gnssMeasurementsNotification);
+ };
+ }
+
+ locAPISetCallbacks(locationCallbacks);
+
+ TrackingOptions options = {};
+ memset(&options, 0, sizeof(TrackingOptions));
+ options.size = sizeof(TrackingOptions);
+ options.minInterval = 1000;
+ options.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ options.powerMode = powerMode;
+ options.tbm = timeBetweenMeasurement;
+ }
+
+ mTracking = true;
+ LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+ locAPIStartTracking(options);
+ return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ mTracking = false;
+ locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+ GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+ LOC_LOGD("%s]: (count: %zu active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ sp<IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+ } else if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface_1_1 != nullptr) {
+ IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface != nullptr) {
+ V1_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+ memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
+ out.multipathIndicator =
+ static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+ out.snrDb = in.signalToNoiseRatioDb;
+ out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
+ __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT);
+ out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.measurementCount; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i]);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ IGnssMeasurementCallback::GnssData& out)
+{
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/1.1/location_api/MeasurementAPIClient.h b/gps/android/1.1/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..5fb307c
--- /dev/null
+++ b/gps/android/1.1/location_api/MeasurementAPIClient.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
+ const sp<IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+ sp<IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+
+ bool mTracking;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/1.1/service.cpp b/gps/android/1.1/service.cpp
new file mode 100644
index 0000000..0cb91f7
--- /dev/null
+++ b/gps/android/1.1/service.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@1.1-service-qti"
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V1_1::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ if (vendorEnhanced) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGE("LOC_HIDL_VERSION not defined.");
+ #endif
+ }
+
+ joinRpcThreadpool();
+
+ } else {
+ ALOGE("Error while registering IGnss 1.1 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/2.0/AGnss.cpp b/gps/android/2.0/AGnss.cpp
new file mode 100644
index 0000000..a48f1a0
--- /dev/null
+++ b/gps/android/2.0/AGnss.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
+ if (nullptr != spAGnss) {
+ spAGnss->statusCb(status.type, status.status);
+ }
+}
+
+void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {
+
+ V2_0::IAGnssCallback::AGnssType aType;
+ IAGnssCallback::AGnssStatusValue aStatus;
+
+ switch (type) {
+ case LOC_AGPS_TYPE_SUPL:
+ aType = IAGnssCallback::AGnssType::SUPL;
+ break;
+ case LOC_AGPS_TYPE_SUPL_ES:
+ aType = IAGnssCallback::AGnssType::SUPL_EIMS;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", type);
+ return;
+ }
+
+ switch (status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status);
+ return;
+ }
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ }
+ else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/AGnss.h b/gps/android/2.0/AGnss.h
new file mode 100644
index 0000000..c442327
--- /dev/null
+++ b/gps/android/2.0/AGnss.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+
+#include <android/hardware/gnss/2.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct AGnss : public V2_0::IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusCb(AGpsExtType type, LocAGpsStatusValue status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
diff --git a/gps/android/2.0/AGnssRil.cpp b/gps/android/2.0/AGnssRil.cpp
new file mode 100644
index 0000000..d8005e4
--- /dev/null
+++ b/gps/android/2.0/AGnssRil.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
+ ENTRY_LOG_CALLFLOW();
+ std::string apn = attributes.apn;
+ if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ bool roaming = false;
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
+ typeout = loc_core::TYPE_WIFI;
+ } else {
+ typeout = loc_core::TYPE_MOBILE;
+ }
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
+ roaming = false;
+ }
+ LOC_LOGd("apn string received is: %s", apn.c_str());
+ mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
+ typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/AGnssRil.h b/gps/android/2.0/AGnssRil.h
new file mode 100644
index 0000000..a04d8aa
--- /dev/null
+++ b/gps/android/2.0/AGnssRil.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/2.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public V2_0::IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
+ Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
diff --git a/gps/android/2.0/Android.mk b/gps/android/2.0/Android.mk
new file mode 100644
index 0000000..c0b91ae
--- /dev/null
+++ b/gps/android/2.0/Android.mk
@@ -0,0 +1,112 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.0-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ AGnssRil.cpp \
+ GnssMeasurement.cpp \
+ GnssConfiguration.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssNi.cpp \
+ GnssDebug.cpp \
+ MeasurementCorrections.cpp \
+ GnssVisibilityControl.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/GnssAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/LocationUtil.cpp \
+
+ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
+LOCAL_CFLAGS += \
+ -DGNSS_HIDL_LEGACY_MEASURMENTS
+endif
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss.measurement_corrections@1.0 \
+ android.hardware.gnss.visibility_control@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.health@2.1 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.0-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.0-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@2.0-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/2.0/Gnss.cpp b/gps/android/2.0/Gnss.cpp
new file mode 100644
index 0000000..823ef6e
--- /dev/null
+++ b/gps/android/2.0/Gnss.cpp
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include "LocationUtil.h"
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi != nullptr) {
+ return mApi;
+ }
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_0);
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
+ } else if (mGnssCbIface != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ } else {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+
+ if (nullptr == mGnssInterface && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+
+ if (nullptr == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+
+ // In case where previous call to setCallback_1_1 or setCallback_2_0, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+
+
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssStop();
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssGeofencingIface == nullptr) {
+ mGnssGeofencingIface = new GnssGeofencing();
+ }
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssBatching == nullptr) {
+ mGnssBatching = new GnssBatching();
+ }
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback or setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+
+
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_1_1 = callback;
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback or setCallback_1_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_0 = callback;
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mAGnssIface_2_0 == nullptr) {
+ mAGnssIface_2_0 = new AGnss(this);
+ }
+ return mAGnssIface_2_0;
+}
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>>
+ Gnss::getExtensionMeasurementCorrections() {
+ // We do not support, so return nullptr to pass VTS
+ return nullptr;
+}
+Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ Gnss::getExtensionVisibilityControl() {
+ ENTRY_LOG_CALLFLOW();
+ if (mVisibCtrl == nullptr) {
+ mVisibCtrl = new GnssVisibilityControl(this);
+ }
+ return mVisibCtrl;
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ return nullptr;
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/Gnss.h b/gps/android/2.0/Gnss.h
new file mode 100644
index 0000000..a403d61
--- /dev/null
+++ b/gps/android/2.0/Gnss.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssConfiguration.h>
+#include <GnssMeasurement.h>
+#include <GnssBatching.h>
+#include <GnssGeofencing.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <MeasurementCorrections.h>
+#include <GnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "GnssAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using ::android::hardware::gnss::measurement_corrections::V1_0::implementation::MeasurementCorrections;
+using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+ Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+ Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+ Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+
+ Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections>>
+ getExtensionMeasurementCorrections() override;
+ Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+
+ Return<bool> injectBestLocation_2_0(const ::android::hardware::gnss::V2_0::GnssLocation& location) override;
+
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+
+
+ /**
+ * This method returns the IGnssVisibilityControl interface.
+ *
+ * @return visibilityControlIface Handle to the IGnssVisibilityControl interface.
+ */
+ Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ getExtensionVisibilityControl() override;
+
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<V1_0::IGnssNi> mGnssNi = nullptr;
+ sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<V1_0::IAGnss> mAGnssIface = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
+ sp<V2_0::IAGnssRil> mGnssRil = nullptr;
+ sp<V2_0::IGnssMeasurement> mGnssMeasurement = nullptr;
+ sp<V2_0::IGnssConfiguration> mGnssConfig = nullptr;
+ sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
+ sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
+ sp<IMeasurementCorrections> mGnssMeasCorr = nullptr;
+ sp<IGnssVisibilityControl> mVisibCtrl = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSS_H
diff --git a/gps/android/2.0/GnssBatching.cpp b/gps/android/2.0/GnssBatching.cpp
new file mode 100644
index 0000000..6a2a09e
--- /dev/null
+++ b/gps/android/2.0/GnssBatching.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mApi != nullptr) {
+ mApi->stopSession();
+ }
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface = nullptr;
+ }
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface_2_0 = nullptr;
+ }
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface_2_0 = callback;
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssBatching.h b/gps/android/2.0/GnssBatching.h
new file mode 100644
index 0000000..4c8d1db
--- /dev/null
+++ b/gps/android/2.0/GnssBatching.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+ Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0 = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
diff --git a/gps/android/2.0/GnssConfiguration.cpp b/gps/android/2.0/GnssConfiguration.cpp
new file mode 100644
index 0000000..55a70dc
--- /dev/null
+++ b/gps/android/2.0/GnssConfiguration.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include "ContextBase.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::GnssConstellationType;
+using namespace loc_core;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ // deprecated function. Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ mGnss->updateConfiguration(config);
+ // Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnss == nullptr) {
+ LOC_LOGe("mGnss is nullptr");
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ config.emergencyExtensionSeconds = emergencyExtensionSeconds;
+
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssConfiguration.h b/gps/android/2.0/GnssConfiguration.h
new file mode 100644
index 0000000..c3de2c9
--- /dev/null
+++ b/gps/android/2.0/GnssConfiguration.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public V2_0::IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<GnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+ Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
diff --git a/gps/android/2.0/GnssDebug.cpp b/gps/android/2.0/GnssDebug.cpp
new file mode 100644
index 0000000..dc0d9f4
--- /dev/null
+++ b/gps/android/2.0/GnssDebug.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V1_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V1_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V1_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+Return<void> GnssDebug::getDebugData_2_0(getDebugData_2_0_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V2_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ }
+ else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V2_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V2_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.v1_0.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.v1_0.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.v1_0.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.v1_0.ephemerisHealth);
+
+ s.v1_0.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.v1_0.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.v1_0.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssDebug.h b/gps/android/2.0/GnssDebug.h
new file mode 100644
index 0000000..8d75bea
--- /dev/null
+++ b/gps/android/2.0/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/2.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+ // Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow.
+ Return<void> getDebugData_2_0(getDebugData_2_0_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
diff --git a/gps/android/2.0/GnssGeofencing.cpp b/gps/android/2.0/GnssGeofencing.cpp
new file mode 100644
index 0000000..b6fc94b
--- /dev/null
+++ b/gps/android/2.0/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssGeofencing.h b/gps/android/2.0/GnssGeofencing.h
new file mode 100644
index 0000000..caa56d0
--- /dev/null
+++ b/gps/android/2.0/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
diff --git a/gps/android/2.0/GnssMeasurement.cpp b/gps/android/2.0/GnssMeasurement.cpp
new file mode 100644
index 0000000..6cb55ca
--- /dev/null
+++ b/gps/android/2.0/GnssMeasurement.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include "GnssMeasurement.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+}
+
+void GnssMeasurement::clearInterfaces() {
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ }
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ clearInterfaces();
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_0 = callback;
+ mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_0(callback, powerMode);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssMeasurement.h b/gps/android/2.0/GnssMeasurement.h
new file mode 100644
index 0000000..7fa66b4
--- /dev/null
+++ b/gps/android/2.0/GnssMeasurement.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public V2_0::IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+ Return<GnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
+ MeasurementAPIClient* mApi;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSMEASUREMENT_H
diff --git a/gps/android/2.0/GnssNi.cpp b/gps/android/2.0/GnssNi.cpp
new file mode 100644
index 0000000..d65a488
--- /dev/null
+++ b/gps/android/2.0/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssNi.h b/gps/android/2.0/GnssNi.h
new file mode 100644
index 0000000..26e281f
--- /dev/null
+++ b/gps/android/2.0/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
diff --git a/gps/android/2.0/GnssVisibilityControl.cpp b/gps/android/2.0/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..5a8c697
--- /dev/null
+++ b/gps/android/2.0/GnssVisibilityControl.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "GnssVisibilityControl.h"
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+static GnssVisibilityControl* spGnssVisibilityControl = nullptr;
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out);
+
+GnssVisibilityControl::GnssVisibilityControl(Gnss* gnss) : mGnss(gnss) {
+ spGnssVisibilityControl = this;
+}
+GnssVisibilityControl::~GnssVisibilityControl() {
+ spGnssVisibilityControl = nullptr;
+}
+
+void GnssVisibilityControl::nfwStatusCb(GnssNfwNotification notification) {
+ if (nullptr != spGnssVisibilityControl) {
+ spGnssVisibilityControl->statusCb(notification);
+ }
+}
+
+bool GnssVisibilityControl::isInEmergencySession() {
+ if (nullptr != spGnssVisibilityControl) {
+ return spGnssVisibilityControl->isE911Session();
+ }
+ return false;
+}
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out)
+{
+ memset(&out, 0, sizeof(IGnssVisibilityControlCallback::NfwNotification));
+ out.proxyAppPackageName = in.proxyAppPackageName;
+ out.protocolStack = (IGnssVisibilityControlCallback::NfwProtocolStack)in.protocolStack;
+ out.otherProtocolStackName = in.otherProtocolStackName;
+ out.requestor = (IGnssVisibilityControlCallback::NfwRequestor)in.requestor;
+ out.requestorId = in.requestorId;
+ out.responseType = (IGnssVisibilityControlCallback::NfwResponseType)in.responseType;
+ out.inEmergencyMode = in.inEmergencyMode;
+ out.isCachedLocation = in.isCachedLocation;
+}
+
+void GnssVisibilityControl::statusCb(GnssNfwNotification notification) {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ IGnssVisibilityControlCallback::NfwNotification nfwNotification;
+
+ // Convert from one structure to another
+ convertGnssNfwNotification(notification, nfwNotification);
+
+ auto r = mGnssVisibilityControlCbIface->nfwNotifyCb(nfwNotification);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+bool GnssVisibilityControl::isE911Session() {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ auto r = mGnssVisibilityControlCbIface->isInEmergencySession();
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ return false;
+ } else {
+ return (r);
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ return false;
+ }
+}
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+
+ /* If the vector is empty we need to disable all NFW clients
+ If there is at least one app in the vector we need to enable
+ all NFW clients */
+ if (0 == proxyApps.size()) {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(false);
+ } else {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(true);
+ }
+
+ return true;
+}
+/**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+Return<bool> GnssVisibilityControl::setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mGnssVisibilityControlCbIface = callback;
+
+ NfwCbInfo cbInfo = {};
+ cbInfo.visibilityControlCb = (void*)nfwStatusCb;
+ cbInfo.isInEmergencySession = (void*)isInEmergencySession;
+
+ mGnss->getGnssInterface()->nfwInit(cbInfo);
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/GnssVisibilityControl.h b/gps/android/2.0/GnssVisibilityControl.h
new file mode 100644
index 0000000..9c26e38
--- /dev/null
+++ b/gps/android/2.0/GnssVisibilityControl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V2_0::implementation::Gnss;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+ GnssVisibilityControl(Gnss* gnss);
+ ~GnssVisibilityControl();
+
+ // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+ Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override;
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override;
+
+ void statusCb(GnssNfwNotification notification);
+ bool isE911Session();
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void nfwStatusCb(GnssNfwNotification notification);
+ static bool isInEmergencySession();
+
+private:
+ Gnss* mGnss = nullptr;
+ sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
diff --git a/gps/android/2.0/MeasurementCorrections.cpp b/gps/android/2.0/MeasurementCorrections.cpp
new file mode 100644
index 0000000..bb75073
--- /dev/null
+++ b/gps/android/2.0/MeasurementCorrections.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "LocSvc_MeasurementCorrectionsInterface"
+
+#include <log_util.h>
+#include "MeasurementCorrections.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+MeasurementCorrections::MeasurementCorrections() {
+}
+
+MeasurementCorrections::~MeasurementCorrections() {
+}
+
+Return<bool> MeasurementCorrections::setCorrections(
+ const ::android::hardware::gnss::measurement_corrections::
+ V1_0::MeasurementCorrections& /*corrections*/) {
+ return true;
+}
+
+Return<bool> MeasurementCorrections::setCallback(
+ const sp<V1_0::IMeasurementCorrectionsCallback>& /*callback*/) {
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/MeasurementCorrections.h b/gps/android/2.0/MeasurementCorrections.h
new file mode 100644
index 0000000..96b1120
--- /dev/null
+++ b/gps/android/2.0/MeasurementCorrections.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
+#define ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
+
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+
+struct MeasurementCorrections : public IMeasurementCorrections {
+ MeasurementCorrections();
+ ~MeasurementCorrections();
+
+// Methods from ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections follow.
+Return<bool> setCorrections(
+ const ::android::hardware::gnss::measurement_corrections::
+ V1_0::MeasurementCorrections& corrections) override;
+
+Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H
diff --git a/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc
new file mode 100644
index 0000000..ad46d5d
--- /dev/null
+++ b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@2.0-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml
new file mode 100644
index 0000000..ff9fb2c
--- /dev/null
+++ b/gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml
@@ -0,0 +1,36 @@
+<!-- Copyright (c) 2019, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ <fqname>@2.0::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/2.0/location_api/BatchingAPIClient.cpp b/gps/android/2.0/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..766c37a
--- /dev/null
+++ b/gps/android/2.0/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,251 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks(callback);
+}
+
+BatchingAPIClient::BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks_2_0(callback);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+void BatchingAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::stopSession()
+{
+ LOC_LOGD("%s]: ", __FUNCTION__);
+ int retVal = -1;
+ if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+void BatchingAPIClient::getBatchedLocation(int last_n_locations)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations);
+ locAPIGetBatchedLocations(mDefaultId, last_n_locations);
+}
+
+void BatchingAPIClient::flushBatchedLocations()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+}
+
+void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+}
+
+void BatchingAPIClient::onBatchingCb(size_t count, Location* location,
+ BatchingOptions /*batchOptions*/)
+{
+ mMutex.lock();
+ auto gnssBatchingCbIface(mGnssBatchingCbIface);
+ auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0);
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (gnssBatchingCbIface_2_0 != nullptr && count > 0) {
+ hidl_vec<V2_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 2.0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<V1_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/BatchingAPIClient.h b/gps/android/2.0/location_api/BatchingAPIClient.h
new file mode 100644
index 0000000..d2d9b4a
--- /dev/null
+++ b/gps/android/2.0/location_api/BatchingAPIClient.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+ BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback);
+ int getBatchSize();
+ int startSession(const V1_0::IGnssBatching::Options& options);
+ int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
+ int stopSession();
+ void getBatchedLocation(int last_n_locations);
+ void flushBatchedLocations();
+
+ inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; }
+
+ // callbacks
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
+
+private:
+ void setCallbacks();
+ ~BatchingAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/2.0/location_api/GeofenceAPIClient.cpp b/gps/android/2.0/location_api/GeofenceAPIClient.cpp
new file mode 100644
index 0000000..a93c988
--- /dev/null
+++ b/gps/android/2.0/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssGeofencingCbIface(callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+
+ locationCallbacks.geofenceBreachCb = nullptr;
+ if (mGnssGeofencingCbIface != nullptr) {
+ locationCallbacks.geofenceBreachCb =
+ [this](GeofenceBreachNotification geofenceBreachNotification) {
+ onGeofenceBreachCb(geofenceBreachNotification);
+ };
+
+ locationCallbacks.geofenceStatusCb =
+ [this](GeofenceStatusNotification geofenceStatusNotification) {
+ onGeofenceStatusCb(geofenceStatusNotification);
+ };
+ }
+
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
+{
+ LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
+ geofence_id, latitude, longitude, radius_meters,
+ last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
+
+ GeofenceOption options;
+ memset(&options, 0, sizeof(GeofenceOption));
+ options.size = sizeof(GeofenceOption);
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT;
+ options.responsiveness = notification_responsiveness_ms;
+
+ GeofenceInfo data;
+ data.size = sizeof(GeofenceInfo);
+ data.latitude = latitude;
+ data.longitude = longitude;
+ data.radius = radius_meters;
+
+ LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ onAddGeofencesCb(1, &err, &geofence_id);
+ }
+}
+
+void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIPauseGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
+ GeofenceBreachTypeMask mask = 0;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ mask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ mask |= GEOFENCE_BREACH_EXIT_BIT;
+ locAPIResumeGeofences(1, &geofence_id, &mask);
+}
+
+void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIRemoveGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceRemoveAll()
+{
+ LOC_LOGD("%s]", __FUNCTION__);
+ // TODO locAPIRemoveAllGeofences();
+}
+
+// callbacks
+void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp));
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
+ if (mGnssGeofencingCbIface != nullptr) {
+ IGnssGeofenceCallback::GeofenceAvailability status =
+ IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
+ if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
+ status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
+ }
+ GnssLocation gnssLocation;
+ memset(&gnssLocation, 0, sizeof(GnssLocation));
+ auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/GeofenceAPIClient.h b/gps/android/2.0/location_api/GeofenceAPIClient.h
new file mode 100644
index 0000000..5bce476
--- /dev/null
+++ b/gps/android/2.0/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+ GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
+
+ void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms);
+ void geofencePause(uint32_t geofence_id);
+ void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions);
+ void geofenceRemove(uint32_t geofence_id);
+ void geofenceRemoveAll();
+
+ // callbacks
+ void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final;
+ void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final;
+ void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+
+private:
+ virtual ~GeofenceAPIClient() = default;
+
+ sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/2.0/location_api/GnssAPIClient.cpp b/gps/android/2.0/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..44007d9
--- /dev/null
+++ b/gps/android/2.0/location_api/GnssAPIClient.cpp
@@ -0,0 +1,728 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnss;
+using ::android::hardware::gnss::V2_0::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out);
+
+GnssAPIClient::GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks_2_0(gpsCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+void GnssAPIClient::initLocationOptions()
+{
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+}
+
+void GnssAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ if (mGnssNiCbIface != nullptr) {
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (!context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) {
+ onGnssNiCb(id, gnssNiNotify);
+ };
+ }
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ mMutex.lock();
+ mGnssCbIface_2_0 = gpsCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = true;
+ mMutex.unlock();
+
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = false;
+ mMutex.unlock();
+
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
+ GnssNiResponse data;
+ switch (userResponse) {
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
+ data = GNSS_NI_RESPONSE_ACCEPT;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
+ data = GNSS_NI_RESPONSE_DENY;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
+ data = GNSS_NI_RESPONSE_NO_RESPONSE;
+ break;
+ default:
+ data = GNSS_NI_RESPONSE_IGNORE;
+ break;
+ }
+
+ locAPIGnssNiResponse(notifId, data);
+}
+
+// these apis using LocationAPIControlClient
+void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
+{
+ LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ GnssAidingData data;
+ memset(&data, 0, sizeof (GnssAidingData));
+ data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_0 != nullptr || gnssCbIface != nullptr) {
+ uint32_t data = 0;
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= V1_0::IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= V1_0::IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT)
+ data |= IGnssCallback::Capabilities::LOW_POWER_MODE;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT)
+ data |= IGnssCallback::Capabilities::SATELLITE_BLACKLIST;
+
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
+ gnssInfo.yearOfHw++; // 2019
+ }
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+
+ if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssSetCapabilitiesCb_2_0(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+
+ }
+
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ bool isTracking = mTracking;
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (flags: %02x isTracking: %d)", __FUNCTION__, location.flags, isTracking);
+
+ if (!isTracking) {
+ return;
+ }
+
+ if (gnssCbIface_2_0 != nullptr) {
+ V2_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface_2_0->gnssLocationCb_2_0(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else {
+ LOC_LOGW("%s] No GNSS Interface ready for gnssLocationCb ", __FUNCTION__);
+ }
+
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %u)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_0 != nullptr) {
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo> svInfoList;
+ convertGnssSvStatus(gnssSvNotification, svInfoList);
+ auto r = gnssCbIface_2_0->gnssSvStatusCb_2_0(svInfoList);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr || gnssCbIface_2_0 != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssCbIface_2_0 nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2.0 ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2.0 SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2.0 SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2.0 ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
+ __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT);
+ out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.numSvs; i++) {
+ convertGnssSvid(in.gnssSvs[i], out.gnssSvList[i].svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, out.gnssSvList[i].constellation);
+ out.gnssSvList[i].cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out.gnssSvList[i].elevationDegrees = in.gnssSvs[i].elevation;
+ out.gnssSvList[i].azimuthDegrees = in.gnssSvs[i].azimuth;
+ out.gnssSvList[i].carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out.gnssSvList[i].svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out)
+{
+ out.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssSvid(in.gnssSvs[i], out[i].v1_0.svid);
+ out[i].v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out[i].v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+ out[i].v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+ out[i].v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out[i].v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+ convertGnssConstellationType(in.gnssSvs[i].type, out[i].constellation);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/GnssAPIClient.h b/gps/android/2.0/location_api/GnssAPIClient.h
new file mode 100644
index 0000000..cfa78c7
--- /dev/null
+++ b/gps/android/2.0/location_api/GnssAPIClient.h
@@ -0,0 +1,115 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnssCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+ GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb);
+ GnssAPIClient(const GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+
+ void setCallbacks();
+ void initLocationOptions();
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+ bool mTracking;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/2.0/location_api/LocationUtil.cpp b/gps/android/2.0/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..961b7b1
--- /dev/null
+++ b/gps/android/2.0/location_api/LocationUtil.cpp
@@ -0,0 +1,334 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+#include <log_util.h>
+#include <inttypes.h>
+#include <gps_extended_c.h>
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssLocation;
+using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V1_0::GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V2_0::GnssLocation));
+ convertGnssLocation(in, out.v1_0);
+
+ if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ out.elapsedRealtime.timestampNs = in.elapsedRealTime;
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+ LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
+ " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
+ " out.elapsedRealtime.flags=0x%X",
+ out.elapsedRealtime.timestampNs,
+ out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
+ }
+}
+
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ convertGnssLocation(in.v1_0, out);
+}
+
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V1_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V1_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V1_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V1_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V1_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V1_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V1_0::GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V2_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V2_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V2_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V2_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V2_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V2_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = V2_0::GnssConstellationType::IRNSS;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V2_0::GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch (in.type) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/LocationUtil.h b/gps/android/2.0/location_api/LocationUtil.h
new file mode 100644
index 0000000..70729e4
--- /dev/null
+++ b/gps/android/2.0/location_api/LocationUtil.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/2.0/types.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/2.0/location_api/MeasurementAPIClient.cpp b/gps/android/2.0/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..425415f
--- /dev/null
+++ b/gps/android/2.0/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,507 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+#include <inttypes.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
+ ::android::hardware::hidl_string& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mGnssMeasurementCbIface_1_1(nullptr),
+ mGnssMeasurementCbIface_2_0(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+void MeasurementAPIClient::clearInterfaces()
+{
+ mGnssMeasurementCbIface = nullptr;
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ mGnssMeasurementCbIface_2_0 = nullptr;
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_1_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking(
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+ if (mGnssMeasurementCbIface_2_0 != nullptr ||
+ mGnssMeasurementCbIface_1_1 != nullptr ||
+ mGnssMeasurementCbIface != nullptr) {
+ locationCallbacks.gnssMeasurementsCb =
+ [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+ onGnssMeasurementsCb(gnssMeasurementsNotification);
+ };
+ }
+
+ locAPISetCallbacks(locationCallbacks);
+
+ TrackingOptions options = {};
+ memset(&options, 0, sizeof(TrackingOptions));
+ options.size = sizeof(TrackingOptions);
+ options.minInterval = 1000;
+ options.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ options.powerMode = powerMode;
+ options.tbm = timeBetweenMeasurement;
+ }
+
+ mTracking = true;
+ LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+ locAPIStartTracking(options);
+ return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ mTracking = false;
+ locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+ GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+ LOC_LOGD("%s]: (count: %u active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr;
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0;
+ } else if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+ } else if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface_2_0 != nullptr) {
+ V2_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_2_0(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface_1_1 != nullptr) {
+ V1_1::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface != nullptr) {
+ V1_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
+ out.multipathIndicator =
+ static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+ out.snrDb = in.signalToNoiseRatioDb;
+ out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
+ __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT);
+ out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.measurementCount; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i]);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
+ convertGnssConstellationType(in.measurements[i].svType, out.measurements[i].constellation);
+ convertGnssMeasurementsCodeType(in.measurements[i].codeType, out.measurements[i].codeType);
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out.measurements[i].v1_1.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+ if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
+ out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
+ }
+ convertGnssClock(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+ if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+ LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
+ " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
+ elapsedRealtime.timestampNs,
+ elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
+ }
+}
+
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
+ ::android::hardware::hidl_string& out)
+{
+ switch(in) {
+ case GNSS_MEASUREMENTS_CODE_TYPE_A:
+ out = "A";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_B:
+ out = "B";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_C:
+ out = "C";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_I:
+ out = "I";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_L:
+ out = "L";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_M:
+ out = "M";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_P:
+ out = "P";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Q:
+ out = "Q";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_S:
+ out = "S";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_W:
+ out = "W";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_X:
+ out = "X";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Y:
+ out = "Y";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Z:
+ out = "Z";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_N:
+ out = "N";
+ break;
+ default:
+ out = "UNKNOWN";
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.0/location_api/MeasurementAPIClient.h b/gps/android/2.0/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..6c2d38d
--- /dev/null
+++ b/gps/android/2.0/location_api/MeasurementAPIClient.h
@@ -0,0 +1,90 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
+ bool mTracking;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/2.0/service.cpp b/gps/android/2.0/service.cpp
new file mode 100644
index 0000000..f7efb18
--- /dev/null
+++ b/gps/android/2.0/service.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@2.0-service-qti"
+
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V2_0::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGI("LOC_HIDL_VERSION not defined.");
+ #endif
+ joinRpcThreadpool();
+ } else {
+ ALOGE("Error while registering IGnss 2.0 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/2.1/AGnss.cpp b/gps/android/2.1/AGnss.cpp
new file mode 100644
index 0000000..c759492
--- /dev/null
+++ b/gps/android/2.1/AGnss.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_AGnssInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static AGnss* spAGnss = nullptr;
+
+AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
+ spAGnss = this;
+}
+
+AGnss::~AGnss() {
+ spAGnss = nullptr;
+}
+
+void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
+ if (nullptr != spAGnss) {
+ spAGnss->statusCb(status.type, status.status);
+ }
+}
+
+void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {
+
+ V2_0::IAGnssCallback::AGnssType aType;
+ IAGnssCallback::AGnssStatusValue aStatus;
+
+ switch (type) {
+ case LOC_AGPS_TYPE_SUPL:
+ aType = IAGnssCallback::AGnssType::SUPL;
+ break;
+ case LOC_AGPS_TYPE_SUPL_ES:
+ aType = IAGnssCallback::AGnssType::SUPL_EIMS;
+ break;
+ default:
+ LOC_LOGE("invalid type: %d", type);
+ return;
+ }
+
+ switch (status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
+ break;
+ case LOC_GPS_AGPS_DATA_CONNECTED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_DONE:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
+ break;
+ case LOC_GPS_AGPS_DATA_CONN_FAILED:
+ aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
+ break;
+ default:
+ LOC_LOGE("invalid status: %d", status);
+ return;
+ }
+
+ if (mAGnssCbIface != nullptr) {
+ auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
+ }
+ }
+ else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return Void();
+ }
+
+ // Save the interface
+ mAGnssCbIface = callback;
+
+ AgpsCbInfo cbInfo = {};
+ cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;
+
+ mGnss->getGnssInterface()->agpsInit(cbInfo);
+ return Void();
+}
+
+Return<bool> AGnss::dataConnClosed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnFailed() {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
+ return true;
+}
+
+Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) {
+
+ if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
+ LOC_LOGE("Null GNSS interface");
+ return false;
+ }
+
+ /* Validate */
+ if(apn.empty()){
+ LOC_LOGE("Invalid APN");
+ return false;
+ }
+
+ LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
+
+ AGpsBearerType bearerType;
+ switch (apnIpType) {
+ case IAGnss::ApnIpType::IPV4:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ case IAGnss::ApnIpType::IPV6:
+ bearerType = AGPS_APN_BEARER_IPV6;
+ break;
+ case IAGnss::ApnIpType::IPV4V6:
+ bearerType = AGPS_APN_BEARER_IPV4V6;
+ break;
+ default:
+ bearerType = AGPS_APN_BEARER_IPV4;
+ break;
+ }
+
+ mGnss->getGnssInterface()->agpsDataConnOpen(
+ LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType);
+ return true;
+}
+
+Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname,
+ int32_t port) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ if (type == IAGnssCallback::AGnssType::SUPL) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
+ } else if (type == IAGnssCallback::AGnssType::C2K) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
+ } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
+ config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
+ } else {
+ LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
+ return false;
+ }
+ config.assistanceServer.hostName = strdup(hostname.c_str());
+ config.assistanceServer.port = port;
+ return mGnss->updateConfiguration(config);
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/AGnss.h b/gps/android/2.1/AGnss.h
new file mode 100644
index 0000000..f6ea997
--- /dev/null
+++ b/gps/android/2.1/AGnss.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
+
+#include <android/hardware/gnss/2.0/IAGnss.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::hardware::gnss::V2_0::IAGnssCallback;
+
+struct Gnss;
+struct AGnss : public V2_0::IAGnss {
+
+ AGnss(Gnss* gnss);
+ ~AGnss();
+ /*
+ * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
+ * These declarations were generated from IAGnss.hal.
+ */
+ Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;
+
+ Return<bool> dataConnClosed() override;
+
+ Return<bool> dataConnFailed() override;
+
+ Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
+ V2_0::IAGnss::ApnIpType apnIpType) override;
+
+ Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
+ const hidl_string& hostname, int32_t port) override;
+
+ void statusCb(AGpsExtType type, LocAGpsStatusValue status);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);
+
+ private:
+ Gnss* mGnss = nullptr;
+ sp<V2_0::IAGnssCallback> mAGnssCbIface = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
diff --git a/gps/android/2.1/AGnssRil.cpp b/gps/android/2.1/AGnssRil.cpp
new file mode 100644
index 0000000..f413e93
--- /dev/null
+++ b/gps/android/2.1/AGnssRil.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc__AGnssRilInterface"
+
+#include <log_util.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sstream>
+#include <string>
+#include "Gnss.h"
+#include "AGnssRil.h"
+#include <DataItemConcreteTypesBase.h>
+
+typedef void* (getLocationInterface)();
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+
+AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
+ ENTRY_LOG_CALLFLOW();
+}
+
+AGnssRil::~AGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
+ ENTRY_LOG_CALLFLOW();
+ // Extra NetworkTypes not available in IAgnssRil enums
+ const int NetworkType_BLUETOOTH = 7;
+ const int NetworkType_ETHERNET = 9;
+ const int NetworkType_PROXY = 16;
+ std::string apn("");
+
+ // for XTRA
+ if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ switch(type)
+ {
+ case IAGnssRil::NetworkType::MOBILE:
+ typeout = loc_core::TYPE_MOBILE;
+ break;
+ case IAGnssRil::NetworkType::WIFI:
+ typeout = loc_core::TYPE_WIFI;
+ break;
+ case IAGnssRil::NetworkType::MMS:
+ typeout = loc_core::TYPE_MMS;
+ break;
+ case IAGnssRil::NetworkType::SUPL:
+ typeout = loc_core::TYPE_SUPL;
+ break;
+ case IAGnssRil::NetworkType::DUN:
+ typeout = loc_core::TYPE_DUN;
+ break;
+ case IAGnssRil::NetworkType::HIPRI:
+ typeout = loc_core::TYPE_HIPRI;
+ break;
+ case IAGnssRil::NetworkType::WIMAX:
+ typeout = loc_core::TYPE_WIMAX;
+ break;
+ default:
+ {
+ int networkType = (int) type;
+ // Handling network types not available in IAgnssRil
+ switch(networkType)
+ {
+ case NetworkType_BLUETOOTH:
+ typeout = loc_core::TYPE_BLUETOOTH;
+ break;
+ case NetworkType_ETHERNET:
+ typeout = loc_core::TYPE_ETHERNET;
+ break;
+ case NetworkType_PROXY:
+ typeout = loc_core::TYPE_PROXY;
+ break;
+ default:
+ typeout = loc_core::TYPE_UNKNOWN;
+ }
+ }
+ break;
+ }
+ mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
+ }
+ return true;
+}
+Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
+ ENTRY_LOG_CALLFLOW();
+ std::string apn = attributes.apn;
+ if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
+ int8_t typeout = loc_core::TYPE_UNKNOWN;
+ bool roaming = false;
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
+ typeout = loc_core::TYPE_WIFI;
+ } else {
+ typeout = loc_core::TYPE_MOBILE;
+ }
+ if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
+ roaming = false;
+ }
+ LOC_LOGd("apn string received is: %s", apn.c_str());
+ mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
+ typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
+ }
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/AGnssRil.h b/gps/android/2.1/AGnssRil.h
new file mode 100644
index 0000000..2bf6156
--- /dev/null
+++ b/gps/android/2.1/AGnssRil.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
+
+#include <android/hardware/gnss/2.0/IAGnssRil.h>
+#include <hidl/Status.h>
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public V2_0::IAGnssRil {
+ AGnssRil(Gnss* gnss);
+ ~AGnssRil();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+ * These declarations were generated from IAGnssRil.hal.
+ */
+ Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
+ return Void();
+ }
+ Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
+ return Void();
+ }
+ Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkAvailability(bool /*available*/,
+ const hidl_string& /*apn*/) override {
+ return false;
+ }
+ Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
+ Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
diff --git a/gps/android/2.1/Android.mk b/gps/android/2.1/Android.mk
new file mode 100644
index 0000000..a947e41
--- /dev/null
+++ b/gps/android/2.1/Android.mk
@@ -0,0 +1,116 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-impl-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ AGnss.cpp \
+ Gnss.cpp \
+ AGnssRil.cpp \
+ GnssMeasurement.cpp \
+ GnssConfiguration.cpp \
+ GnssBatching.cpp \
+ GnssGeofencing.cpp \
+ GnssNi.cpp \
+ GnssDebug.cpp \
+ GnssAntennaInfo.cpp \
+ MeasurementCorrections.cpp \
+ GnssVisibilityControl.cpp
+
+LOCAL_SRC_FILES += \
+ location_api/GnssAPIClient.cpp \
+ location_api/MeasurementAPIClient.cpp \
+ location_api/GeofenceAPIClient.cpp \
+ location_api/BatchingAPIClient.cpp \
+ location_api/LocationUtil.cpp \
+
+ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
+LOCAL_CFLAGS += \
+ -DGNSS_HIDL_LEGACY_MEASURMENTS
+endif
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/location_api
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers \
+ liblocbatterylistener_headers
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libhidlbase \
+ libcutils \
+ libutils \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss@2.1 \
+ android.hardware.gnss.measurement_corrections@1.0 \
+ android.hardware.gnss.measurement_corrections@1.1 \
+ android.hardware.gnss.visibility_control@1.0 \
+ android.hardware.health@1.0 \
+ android.hardware.health@2.0 \
+ android.hardware.health@2.1 \
+ android.hardware.power@1.2 \
+ libbase
+
+LOCAL_SHARED_LIBRARIES += \
+ libloc_core \
+ libgps.utils \
+ libdl \
+ liblocation_api \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+LOCAL_STATIC_LIBRARIES := liblocbatterylistener
+LOCAL_STATIC_LIBRARIES += libhealthhalutils
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@2.1-service-qti
+LOCAL_SANITIZE += $(GNSS_SANITIZE)
+# activate the following line for debug purposes only, comment out for production
+#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
+LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.1-service-qti.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_INIT_RC := android.hardware.gnss@2.1-service-qti.rc
+LOCAL_SRC_FILES := \
+ service.cpp \
+
+LOCAL_HEADER_LIBRARIES := \
+ libgps.utils_headers \
+ libloc_core_headers \
+ libloc_pla_headers \
+ liblocation_api_headers
+
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libgps.utils \
+ libqti_vndfwk_detect \
+
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ android.hardware.gnss@1.0 \
+ android.hardware.gnss@1.1 \
+ android.hardware.gnss@2.0 \
+ android.hardware.gnss@2.1 \
+
+LOCAL_CFLAGS += $(GNSS_CFLAGS)
+
+ifneq ($(LOC_HIDL_VERSION),)
+LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/gps/android/2.1/Gnss.cpp b/gps/android/2.1/Gnss.cpp
new file mode 100644
index 0000000..37e1cc5
--- /dev/null
+++ b/gps/android/2.1/Gnss.cpp
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssInterface"
+#define LOG_NDEBUG 0
+
+#include <fstream>
+#include <log_util.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "Gnss.h"
+#include "LocationUtil.h"
+#include "battery_listener.h"
+#include "loc_misc_utils.h"
+
+typedef const GnssInterface* (getLocationInterface)();
+
+#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
+#define DELIMITER ";"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
+using ::android::hardware::gnss::measurement_corrections::V1_1::
+ implementation::MeasurementCorrections;
+static sp<Gnss> sGnss;
+static std::string getVersionString() {
+ static std::string version;
+ if (!version.empty())
+ return version;
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware", value, "unknown");
+ version.append(value).append(DELIMITER);
+
+ std::ifstream in(IMAGES_INFO_FILE);
+ std::string s;
+ while(getline(in, s)) {
+ std::size_t found = s.find("CRM:");
+ if (std::string::npos == found) {
+ continue;
+ }
+
+ // skip over space characters after "CRM:"
+ const char* substr = s.c_str();
+ found += 4;
+ while (0 != substr[found] && isspace(substr[found])) {
+ found++;
+ }
+ if (s.find("11:") != found) {
+ continue;
+ }
+ s.erase(0, found + 3);
+
+ found = s.find_first_of("\r\n");
+ if (std::string::npos != found) {
+ s.erase(s.begin() + found, s.end());
+ }
+ version.append(s).append(DELIMITER);
+ }
+ return version;
+}
+
+void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnss != nullptr) {
+ mGnss->getGnssInterface()->resetNetworkInfo();
+ mGnss->cleanup();
+ }
+}
+
+void location_on_battery_status_changed(bool charging) {
+ LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
+ if (sGnss != nullptr) {
+ sGnss->getGnssInterface()->updateBatteryStatus(charging);
+ }
+}
+Gnss::Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ sGnss = this;
+ // initilize gnss interface at first in case needing notify battery status
+ sGnss->getGnssInterface()->initialize();
+ // register health client to listen on battery change
+ loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
+ // clear pending GnssConfig
+ memset(&mPendingConfig, 0, sizeof(GnssConfig));
+ mGnssDeathRecipient = new GnssDeathRecipient(this);
+}
+
+Gnss::~Gnss() {
+ ENTRY_LOG_CALLFLOW();
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+ sGnss = nullptr;
+}
+
+GnssAPIClient* Gnss::getApi() {
+ if (mApi != nullptr) {
+ return mApi;
+ }
+
+ if (mGnssCbIface_2_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_1);
+ } else if (mGnssCbIface_2_0 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_2_0);
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
+ } else if (mGnssCbIface != nullptr) {
+ mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
+ } else {
+ LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
+ return mApi;
+ }
+
+ if (mPendingConfig.size == sizeof(GnssConfig)) {
+ // we have pending GnssConfig
+ mApi->gnssConfigurationUpdate(mPendingConfig);
+ // clear size to invalid mPendingConfig
+ mPendingConfig.size = 0;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ }
+ }
+
+ return mApi;
+}
+
+const GnssInterface* Gnss::getGnssInterface() {
+ static bool getGnssInterfaceFailed = false;
+ if (mGnssInterface == nullptr && !getGnssInterfaceFailed) {
+ void * libHandle = nullptr;
+ getLocationInterface* getter = (getLocationInterface*)
+ dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
+ if (NULL == getter) {
+ getGnssInterfaceFailed = true;
+ } else {
+ mGnssInterface = (GnssInterface*)(*getter)();
+ }
+ }
+ return mGnssInterface;
+}
+
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+
+ // In case where previous call to setCallback_1_1/setCallback_2_0/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface = callback;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+ return true;
+}
+
+Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ mGnssNiCbIface = callback;
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
+ }
+ return true;
+}
+
+Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssConfigurationUpdate(gnssConfig);
+ } else if (gnssConfig.flags != 0) {
+ // api is not ready yet, update mPendingConfig with gnssConfig
+ mPendingConfig.size = sizeof(GnssConfig);
+
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ mPendingConfig.gpsLock = gnssConfig.gpsLock;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ mPendingConfig.suplVersion = gnssConfig.suplVersion;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
+ mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
+ mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
+ if (mPendingConfig.assistanceServer.hostName != nullptr) {
+ free((void*)mPendingConfig.assistanceServer.hostName);
+ mPendingConfig.assistanceServer.hostName =
+ strdup(gnssConfig.assistanceServer.hostName);
+ }
+ mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
+ mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
+ }
+ if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
+ }
+ }
+ return true;
+}
+
+Return<bool> Gnss::start() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStart();
+ }
+ return retVal;
+}
+
+Return<bool> Gnss::stop() {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssStop();
+ }
+ return retVal;
+}
+
+Return<void> Gnss::cleanup() {
+ ENTRY_LOG_CALLFLOW();
+
+ if (mApi != nullptr) {
+ mApi->gnssStop();
+ mApi->gnssDisable();
+ }
+
+ return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int32_t uncertaintyMs) {
+ return true;
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) {
+ ENTRY_LOG_CALLFLOW();
+ GnssAPIClient* api = getApi();
+ if (api) {
+ api->gnssDeleteAidingData(aidingDataFlags);
+ }
+ return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+ ENTRY_LOG_CALLFLOW();
+ // deprecated function. Must return nullptr to pass VTS
+ return nullptr;
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr) {
+ mGnssMeasurement = new GnssMeasurement();
+ }
+ return mGnssMeasurement;
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssGeofencingIface == nullptr) {
+ mGnssGeofencingIface = new GnssGeofencing();
+ }
+ return mGnssGeofencingIface;
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssBatching == nullptr) {
+ mGnssBatching = new GnssBatching();
+ }
+ return mGnssBatching;
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_2_0/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_1_1 = callback;
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ bool lowPowerMode) {
+ ENTRY_LOG_CALLFLOW();
+ bool retVal = false;
+ GnssAPIClient* api = getApi();
+ if (api) {
+ GnssPowerMode powerMode = lowPowerMode?
+ GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
+ retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
+ preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
+ }
+ return retVal;
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr)
+ mGnssConfig = new GnssConfiguration(this);
+ return mGnssConfig;
+}
+
+Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
+ ENTRY_LOG_CALLFLOW();
+ if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ return;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_1 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_1->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_2_0 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
+ auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
+ request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else if (mGnssCbIface_1_1 != nullptr) {
+ // For emergency mode, request DBH (Device based hybrid) location
+ // Mark Independent from GNSS flag to false.
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
+ if (!r.isOk()) {
+ LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
+ }
+ } else {
+ LOC_LOGe("ODCPI request not supported.");
+ }
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_1_1/setCallback_2_1, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ mApi->gnssUpdateCallbacks_2_1(nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_1 = nullptr;
+ }
+
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_0 = callback;
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mAGnssIface_2_0 == nullptr) {
+ mAGnssIface_2_0 = new AGnss(this);
+ }
+ return mAGnssIface_2_0;
+}
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+
+ if (mGnssRil == nullptr) {
+ mGnssRil = new AGnssRil(this);
+ }
+ return mGnssRil;
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+ ENTRY_LOG_CALLFLOW();
+#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
+ return nullptr;
+#else
+ if (mGnssMeasurement == nullptr)
+ mGnssMeasurement = new GnssMeasurement();
+ return mGnssMeasurement;
+#endif
+}
+
+Return<sp<IMeasurementCorrectionsV1_0>>
+ Gnss::getExtensionMeasurementCorrections() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasCorr == nullptr) {
+ mGnssMeasCorr = new MeasurementCorrections(this);
+ }
+ return mGnssMeasCorr;
+}
+
+Return<sp<IMeasurementCorrectionsV1_1>>
+ Gnss::getExtensionMeasurementCorrections_1_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasCorr == nullptr) {
+ mGnssMeasCorr = new MeasurementCorrections(this);
+ }
+ return mGnssMeasCorr;
+}
+
+Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ Gnss::getExtensionVisibilityControl() {
+ ENTRY_LOG_CALLFLOW();
+ if (mVisibCtrl == nullptr) {
+ mVisibCtrl = new GnssVisibilityControl(this);
+ }
+ return mVisibCtrl;
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
+ ENTRY_LOG_CALLFLOW();
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (nullptr != gnssInterface) {
+ Location location = {};
+ convertGnssLocation(gnssLocation, location);
+ gnssInterface->odcpiInject(location);
+ }
+ return true;
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssDebug == nullptr) {
+ mGnssDebug = new GnssDebug(this);
+ }
+ return mGnssDebug;
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+ return nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+ ENTRY_LOG_CALLFLOW();
+ auto r = callback->gnssNameCb(getVersionString());
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNameCb description=%s",
+ __func__, r.description().c_str());
+ }
+
+ // In case where previous call to setCallback/setCallback_1_1/setCallback_2_0, then
+ // we need to cleanup these interfaces/callbacks here since we no longer
+ // do so in cleanup() function to keep callbacks around after cleanup()
+ if (mApi != nullptr) {
+ mApi->gnssUpdateCallbacks(nullptr, nullptr);
+ mApi->gnssUpdateCallbacks_2_0(nullptr);
+ }
+ mGnssNiCbIface = nullptr;
+ if (mGnssCbIface != nullptr) {
+ mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface = nullptr;
+ }
+ if (mGnssCbIface_1_1 != nullptr) {
+ mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_1_1 = nullptr;
+ }
+ if (mGnssCbIface_2_0 != nullptr) {
+ mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
+ mGnssCbIface_2_0 = nullptr;
+ }
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
+ }
+ mGnssCbIface_2_1 = callback;
+ if (mGnssCbIface_2_1 != nullptr) {
+ mGnssCbIface_2_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
+ }
+
+ const GnssInterface* gnssInterface = getGnssInterface();
+ if (gnssInterface != nullptr) {
+ OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
+ odcpiRequestCb(odcpiRequest);
+ };
+ gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
+ }
+
+ GnssAPIClient* api = getApi();
+ if (api != nullptr) {
+ api->gnssUpdateCallbacks_2_1(mGnssCbIface_2_1);
+ api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
+ api->requestCapabilities();
+ }
+
+ return true;
+}
+Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssMeasurement == nullptr) {
+ mGnssMeasurement = new GnssMeasurement();
+ }
+ return mGnssMeasurement;
+}
+Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssConfig == nullptr) {
+ mGnssConfig = new GnssConfiguration(this);
+ }
+ return mGnssConfig;
+}
+
+Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnssAntennaInfo == nullptr) {
+ mGnssAntennaInfo = new GnssAntennaInfo(this);
+ }
+ return mGnssAntennaInfo;
+}
+
+V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
+ ENTRY_LOG_CALLFLOW();
+ V1_0::IGnss* iface = nullptr;
+ iface = new Gnss();
+ if (iface == nullptr) {
+ LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
+ }
+ return iface;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/Gnss.h b/gps/android/2.1/Gnss.h
new file mode 100644
index 0000000..c383882
--- /dev/null
+++ b/gps/android/2.1/Gnss.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssConfiguration.h>
+#include <GnssMeasurement.h>
+#include <GnssBatching.h>
+#include <GnssGeofencing.h>
+#include <GnssNi.h>
+#include <GnssDebug.h>
+#include <GnssAntennaInfo.h>
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <MeasurementCorrections.h>
+#include <GnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "GnssAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using IMeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using IMeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
+using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+
+struct Gnss : public IGnss {
+ Gnss();
+ ~Gnss();
+
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+ * These declarations were generated from Gnss.hal.
+ */
+ Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+ Return<bool> start() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+ Return<bool> injectLocation(double latitudeDegrees,
+ double longitudeDegrees,
+ float accuracyMeters) override;
+ Return<bool> injectTime(int64_t timeMs,
+ int64_t timeReferenceMs,
+ int32_t uncertaintyMs) override;
+ Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+ Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs) override;
+ Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+ Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+ Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+ Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+ Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+ Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+ Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+
+ inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
+ return nullptr;
+ }
+
+ inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
+ return nullptr;
+ }
+
+ Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
+ Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+ Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs, bool lowPowerMode) override;
+ Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+ Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+ Return<bool> injectBestLocation(const GnssLocation& location) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
+ Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+ Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+ Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+
+ Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+ Return<sp<IMeasurementCorrectionsV1_0>> getExtensionMeasurementCorrections() override;
+ Return<sp<IMeasurementCorrectionsV1_1>> getExtensionMeasurementCorrections_1_1() override;
+ Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+
+ Return<bool> injectBestLocation_2_0(
+ const ::android::hardware::gnss::V2_0::GnssLocation& location) override;
+
+ Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+ Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+ Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
+ getExtensionVisibilityControl() override;
+
+ // Methods from ::android::hardware::gnss::V2_1::IGnss follow.
+ Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+ Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+ Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
+ Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
+
+ // These methods are not part of the IGnss base class.
+ GnssAPIClient* getApi();
+ Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
+ Return<bool> updateConfiguration(GnssConfig& gnssConfig);
+ const GnssInterface* getGnssInterface();
+
+ // Callback for ODCPI request
+ void odcpiRequestCb(const OdcpiRequestInfo& request);
+
+ private:
+ struct GnssDeathRecipient : hidl_death_recipient {
+ GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
+ }
+ ~GnssDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<Gnss> mGnss;
+ };
+
+ private:
+ sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;
+
+ sp<V1_0::IGnssNi> mGnssNi = nullptr;
+ sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
+ sp<V1_0::IAGnss> mAGnssIface = nullptr;
+ sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
+ sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
+ sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
+ sp<V2_0::IAGnssRil> mGnssRil = nullptr;
+ sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
+ sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssCallback> mGnssCbIface_2_1 = nullptr;
+ sp<V2_1::IGnssMeasurement> mGnssMeasurement = nullptr;
+ sp<V2_1::IGnssConfiguration> mGnssConfig = nullptr;
+ sp<V2_1::IGnssAntennaInfo> mGnssAntennaInfo = nullptr;
+ sp<IMeasurementCorrectionsV1_1> mGnssMeasCorr = nullptr;
+ sp<IGnssVisibilityControl> mVisibCtrl = nullptr;
+
+ GnssAPIClient* mApi = nullptr;
+ GnssConfig mPendingConfig;
+ const GnssInterface* mGnssInterface = nullptr;
+};
+
+extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
diff --git a/gps/android/2.1/GnssAntennaInfo.cpp b/gps/android/2.1/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..62c4cc7
--- /dev/null
+++ b/gps/android/2.1/GnssAntennaInfo.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "LocSvc_GnssAntennaInfoInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssAntennaInfo.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+static GnssAntennaInfo* spGnssAntennaInfo = nullptr;
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfos);
+
+void GnssAntennaInfo::GnssAntennaInfoDeathRecipient::serviceDied(uint64_t cookie,
+ const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+ // However, we need to inform the adapter that the service has died
+ if (nullptr == spGnssAntennaInfo) {
+ LOC_LOGE("%s]: spGnssAntennaInfo is nullptr", __FUNCTION__);
+ return;
+ }
+ if (nullptr == spGnssAntennaInfo->mGnss) {
+ LOC_LOGE("%s]: spGnssAntennaInfo->mGnss is nullptr", __FUNCTION__);
+ return;
+ }
+
+ spGnssAntennaInfo->mGnss->getGnssInterface()->antennaInfoClose();
+}
+
+static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& out) {
+
+ uint32_t vecSize, numberOfRows, numberOfColumns;
+ vecSize = in.size();
+ out.resize(vecSize);
+ for (uint32_t i = 0; i < vecSize; i++) {
+ out[i].carrierFrequencyMHz = in[i].carrierFrequencyMHz;
+ out[i].phaseCenterOffsetCoordinateMillimeters.x =
+ in[i].phaseCenterOffsetCoordinateMillimeters.x;
+ out[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty;
+ out[i].phaseCenterOffsetCoordinateMillimeters.y =
+ in[i].phaseCenterOffsetCoordinateMillimeters.y;
+ out[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty;
+ out[i].phaseCenterOffsetCoordinateMillimeters.z =
+ in[i].phaseCenterOffsetCoordinateMillimeters.z;
+ out[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty =
+ in[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty;
+
+ numberOfRows = in[i].phaseCenterVariationCorrectionMillimeters.size();
+ out[i].phaseCenterVariationCorrectionMillimeters.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].phaseCenterVariationCorrectionMillimeters[j].size();
+ out[i].phaseCenterVariationCorrectionMillimeters[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].phaseCenterVariationCorrectionMillimeters[j].row[k] =
+ in[i].phaseCenterVariationCorrectionMillimeters[j][k];
+ }
+ }
+
+ numberOfRows = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters.size();
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].size();
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].
+ row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].row[k] =
+ in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j][k];
+ }
+ }
+
+ numberOfRows = in[i].signalGainCorrectionDbi.size();
+ out[i].signalGainCorrectionDbi.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].signalGainCorrectionDbi[j].size();
+ out[i].signalGainCorrectionDbi[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].signalGainCorrectionDbi[j].row[k] = in[i].signalGainCorrectionDbi[j][k];
+ }
+ }
+
+ numberOfRows = in[i].signalGainCorrectionUncertaintyDbi.size();
+ out[i].signalGainCorrectionUncertaintyDbi.resize(numberOfRows);
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ numberOfColumns = in[i].signalGainCorrectionUncertaintyDbi[j].size();
+ out[i].signalGainCorrectionUncertaintyDbi[j].row.resize(numberOfColumns);
+ for (uint32_t k = 0; k < numberOfColumns; k++) {
+ out[i].signalGainCorrectionUncertaintyDbi[j].row[k] =
+ in[i].signalGainCorrectionUncertaintyDbi[j][k];
+ }
+ }
+ }
+}
+
+GnssAntennaInfo::GnssAntennaInfo(Gnss* gnss) : mGnss(gnss) {
+ mGnssAntennaInfoDeathRecipient = new GnssAntennaInfoDeathRecipient(this);
+ spGnssAntennaInfo = this;
+}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+ spGnssAntennaInfo = nullptr;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+Return<GnssAntennaInfo::GnssAntennaInfoStatus>
+ GnssAntennaInfo::setCallback(const sp<IGnssAntennaInfoCallback>& callback) {
+ uint32_t retValue;
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return GnssAntennaInfoStatus::ERROR_GENERIC;
+ }
+
+ mGnssAntennaInfoCbIface = callback;
+ retValue = mGnss->getGnssInterface()->antennaInfoInit(aiGnssAntennaInfoCb);
+
+ switch (retValue) {
+ case ANTENNA_INFO_SUCCESS: return GnssAntennaInfoStatus::SUCCESS;
+ case ANTENNA_INFO_ERROR_ALREADY_INIT: return GnssAntennaInfoStatus::ERROR_ALREADY_INIT;
+ case ANTENNA_INFO_ERROR_GENERIC:
+ default: return GnssAntennaInfoStatus::ERROR_GENERIC;
+ }
+}
+
+Return<void> GnssAntennaInfo::close(void) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->getGnssInterface()->antennaInfoClose();
+
+ return Void();
+}
+
+void GnssAntennaInfo::aiGnssAntennaInfoCb
+ (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+ if (nullptr != spGnssAntennaInfo) {
+ spGnssAntennaInfo->gnssAntennaInfoCb(gnssAntennaInformations);
+ }
+}
+
+void GnssAntennaInfo::gnssAntennaInfoCb
+ (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
+
+ if (mGnssAntennaInfoCbIface != nullptr) {
+ hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+
+ // Convert from one structure to another
+ convertGnssAntennaInfo(gnssAntennaInformations, antennaInfos);
+
+ auto r = mGnssAntennaInfoCbIface->gnssAntennaInfoCb(antennaInfos);
+ if (!r.isOk()) {
+ LOC_LOGw("Error antenna info cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssAntennaInfo.h b/gps/android/2.1/GnssAntennaInfo.h
new file mode 100644
index 0000000..02ddd28
--- /dev/null
+++ b/gps/android/2.1/GnssAntennaInfo.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+
+#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssAntennaInfo : public IGnssAntennaInfo {
+ GnssAntennaInfo(Gnss* gnss);
+ ~GnssAntennaInfo();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_1::IGnssAntennaInfo follow.
+ * These declarations were generated from IGnssAntennaInfo.hal.
+ */
+ Return<GnssAntennaInfoStatus>
+ setCallback(const sp<IGnssAntennaInfoCallback>& callback) override;
+ Return<void> close(void) override;
+
+ void gnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+ static void aiGnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+ private:
+ struct GnssAntennaInfoDeathRecipient : hidl_death_recipient {
+ GnssAntennaInfoDeathRecipient(sp<GnssAntennaInfo> gnssAntennaInfo) :
+ mGnssAntennaInfo(gnssAntennaInfo) {
+ }
+ ~GnssAntennaInfoDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssAntennaInfo> mGnssAntennaInfo;
+ };
+
+ private:
+ sp<GnssAntennaInfoDeathRecipient> mGnssAntennaInfoDeathRecipient = nullptr;
+ sp<IGnssAntennaInfoCallback> mGnssAntennaInfoCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
diff --git a/gps/android/2.1/GnssBatching.cpp b/gps/android/2.1/GnssBatching.cpp
new file mode 100644
index 0000000..73e3532
--- /dev/null
+++ b/gps/android/2.1/GnssBatching.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssBatchingInterface"
+
+#include <log_util.h>
+#include <BatchingAPIClient.h>
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssBatching::GnssBatchingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+}
+
+GnssBatching::GnssBatching() : mApi(nullptr) {
+ mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this);
+}
+
+GnssBatching::~GnssBatching() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<V1_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface = callback;
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+ uint16_t ret = 0;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->getBatchSize();
+ }
+ return ret;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->startSession(options);
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::flush() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->flushBatchedLocations();
+ }
+ return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+ bool ret = false;
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ ret = mApi->stopSession();
+ }
+ return ret;
+}
+
+Return<void> GnssBatching::cleanup() {
+ if (mApi != nullptr) {
+ mApi->stopSession();
+ }
+ if (mGnssBatchingCbIface != nullptr) {
+ mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface = nullptr;
+ }
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ mGnssBatchingCbIface_2_0 = nullptr;
+ }
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+Return<bool> GnssBatching::init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__);
+ mApi->destroy();
+ mApi = nullptr;
+ }
+
+ mApi = new BatchingAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ return false;
+ }
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->unlinkToDeath(mGnssBatchingDeathRecipient);
+ }
+ mGnssBatchingCbIface_2_0 = callback;
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ mGnssBatchingCbIface_2_0->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssBatching.h b/gps/android/2.1/GnssBatching.h
new file mode 100644
index 0000000..908748f
--- /dev/null
+++ b/gps/android/2.1/GnssBatching.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+class BatchingAPIClient;
+struct GnssBatching : public IGnssBatching {
+ GnssBatching();
+ ~GnssBatching();
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+ Return<bool> init(const sp<V1_0::IGnssBatchingCallback>& callback) override;
+ Return<uint16_t> getBatchSize() override;
+ Return<bool> start(const IGnssBatching::Options& options ) override;
+ Return<void> flush() override;
+ Return<bool> stop() override;
+ Return<void> cleanup() override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow.
+ Return<bool> init_2_0(const sp<V2_0::IGnssBatchingCallback>& callback) override;
+
+ private:
+ struct GnssBatchingDeathRecipient : hidl_death_recipient {
+ GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) :
+ mGnssBatching(gnssBatching) {
+ }
+ ~GnssBatchingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssBatching> mGnssBatching;
+ };
+
+ private:
+ sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface = nullptr;
+ BatchingAPIClient* mApi = nullptr;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0 = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSBATCHING_H
diff --git a/gps/android/2.1/GnssConfiguration.cpp b/gps/android/2.1/GnssConfiguration.cpp
new file mode 100644
index 0000000..b6077ae
--- /dev/null
+++ b/gps/android/2.1/GnssConfiguration.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssConfigurationInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssConfiguration.h"
+#include "ContextBase.h"
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using namespace loc_core;
+
+GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) {
+}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled) {
+ // deprecated function. Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
+ switch (version) {
+ case 0x00020004:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4;
+ break;
+ case 0x00020002:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2;
+ break;
+ case 0x00020000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0;
+ break;
+ case 0x00010000:
+ config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
+ switch (mode) {
+ case 0:
+ config.suplModeMask = 0; // STANDALONE ONLY
+ break;
+ case 1:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT;
+ break;
+ case 2:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ case 3:
+ config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode);
+ return false;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfileMask) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ config.lppProfileMask = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; //default
+
+ if (lppProfileMask & (1<<0)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<1)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT;
+ }
+ if (lppProfileMask & (1<<2)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT;
+ }
+ if (lppProfileMask & (1<<3)) {
+ config.lppProfileMask |= GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+
+ config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
+ if (protocol & (1<<0)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT;
+ }
+ if (protocol & (1<<1)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<2)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT;
+ }
+ if (protocol & (1<<3)) {
+ config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT;
+ }
+
+ return mGnss->updateConfiguration(config);
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
+ switch (lock) {
+ case 0:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ break;
+ case 1:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO;
+ break;
+ case 2:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI;
+ break;
+ case 3:
+ config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ break;
+ default:
+ LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock);
+ return false;
+ }
+
+ mGnss->updateConfiguration(config);
+ // Must return false to pass VTS
+ return false;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
+ config.emergencyPdnForEmergencySupl = (enabled ?
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES :
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO);
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+ const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, (GnssConstellationType)blacklist[idx].constellation,
+ blacklist[idx].svid) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+ const int16_t svid) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = svid;
+
+ switch(constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = 0;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::IRNSS:
+ copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+ svIdOffset = 0;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+bool GnssConfiguration::setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource) {
+
+ bool retVal = true;
+ uint16_t svIdOffset = 0;
+ copyToSource.size = sizeof(GnssSvIdSource);
+ copyToSource.svId = copyFromSource.svid;
+
+ switch(copyFromSource.constellation) {
+ case GnssConstellationType::GPS:
+ copyToSource.constellation = GNSS_SV_TYPE_GPS;
+ LOC_LOGe("GPS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::SBAS:
+ copyToSource.constellation = GNSS_SV_TYPE_SBAS;
+ LOC_LOGe("SBAS SVs can't be blacklisted.");
+ retVal = false;
+ break;
+ case GnssConstellationType::GLONASS:
+ copyToSource.constellation = GNSS_SV_TYPE_GLONASS;
+ svIdOffset = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::QZSS:
+ copyToSource.constellation = GNSS_SV_TYPE_QZSS;
+ svIdOffset = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::BEIDOU:
+ copyToSource.constellation = GNSS_SV_TYPE_BEIDOU;
+ svIdOffset = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::GALILEO:
+ copyToSource.constellation = GNSS_SV_TYPE_GALILEO;
+ svIdOffset = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID - 1;
+ break;
+ case GnssConstellationType::IRNSS:
+ copyToSource.constellation = GNSS_SV_TYPE_NAVIC;
+ svIdOffset = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID - 1;
+ break;
+ default:
+ copyToSource.constellation = GNSS_SV_TYPE_UNKNOWN;
+ LOC_LOGe("Invalid constellation %hhu", copyFromSource.constellation);
+ retVal = false;
+ break;
+ }
+
+ if (copyToSource.svId > 0 && svIdOffset > 0) {
+ copyToSource.svId += svIdOffset;
+ }
+
+ return retVal;
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+ ENTRY_LOG_CALLFLOW();
+ if (mGnss == nullptr) {
+ LOC_LOGe("mGnss is nullptr");
+ return false;
+ }
+
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
+ config.emergencyExtensionSeconds = emergencyExtensionSeconds;
+
+ return mGnss->updateConfiguration(config);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist_2_1(
+ const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) {
+ ENTRY_LOG_CALLFLOW();
+ if (nullptr == mGnss) {
+ LOC_LOGe("mGnss is null");
+ return false;
+ }
+
+ // blValid is true if blacklist is empty, i.e. clearing the BL;
+ // if blacklist is not empty, blValid is initialied to false, and later
+ // updated in the for loop to become true only if there is at least
+ // one {constellation, svid} in the list that is valid.
+ bool blValid = (0 == blacklist.size());
+ GnssConfig config;
+ memset(&config, 0, sizeof(GnssConfig));
+ config.size = sizeof(GnssConfig);
+ config.flags = GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ config.blacklistedSvIds.clear();
+
+ GnssSvIdSource source = {};
+ for (int idx = 0; idx < (int)blacklist.size(); idx++) {
+ // Set blValid true if any one source is valid
+ blValid = setBlacklistedSource(source, blacklist[idx]) || blValid;
+ config.blacklistedSvIds.push_back(source);
+ }
+
+ // Update configuration only if blValid is true
+ // i.e. only if atleast one source is valid for blacklisting
+ return (blValid && mGnss->updateConfiguration(config));
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssConfiguration.h b/gps/android/2.1/GnssConfiguration.h
new file mode 100644
index 0000000..f000dbd
--- /dev/null
+++ b/gps/android/2.1/GnssConfiguration.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+
+ /* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct Gnss;
+struct GnssConfiguration : public V2_1::IGnssConfiguration {
+ GnssConfiguration(Gnss* gnss);
+ ~GnssConfiguration() = default;
+
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+ * These declarations were generated from IGnssConfiguration.hal.
+ */
+ Return<bool> setSuplVersion(uint32_t version) override;
+ Return<bool> setSuplMode(uint8_t mode) override;
+ Return<bool> setSuplEs(bool enabled) override;
+ Return<bool> setLppProfile(uint8_t lppProfileMask) override;
+ Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+ Return<bool> setEmergencySuplPdn(bool enable) override;
+ Return<bool> setGpsLock(uint8_t lock) override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist(
+ const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+ Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+ // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+ Return<bool> setBlacklist_2_1(
+ const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+ private:
+ Gnss* mGnss = nullptr;
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource,
+ const GnssConfiguration::BlacklistedSource& copyFromSource);
+ bool setBlacklistedSource(
+ GnssSvIdSource& copyToSource, const GnssConstellationType& constellation,
+ const int16_t svid);
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
diff --git a/gps/android/2.1/GnssDebug.cpp b/gps/android/2.1/GnssDebug.cpp
new file mode 100644
index 0000000..27ff964
--- /dev/null
+++ b/gps/android/2.1/GnssDebug.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssDebugInterface"
+
+#include <log/log.h>
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssDebug.h"
+#include "LocationUtil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+
+#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
+#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000)
+#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500)
+#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180)
+
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN (999) // 999 ns
+#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX (1.57783680E17) // 5 years in ns
+#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm
+
+GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
+{
+}
+
+/*
+ * This methods requests position, time and satellite ephemeris debug information
+ * from the HAL.
+ *
+ * @return void
+*/
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V1_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V1_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V1_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
+
+ s.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+Return<void> GnssDebug::getDebugData_2_0(getDebugData_2_0_cb _hidl_cb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ V2_0::IGnssDebug::DebugData data = { };
+
+ if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
+ LOC_LOGE("GnssDebug - Null GNSS interface");
+ _hidl_cb(data);
+ return Void();
+ }
+
+ // get debug report snapshot via hal interface
+ GnssDebugReport reports = { };
+ mGnss->getGnssInterface()->getDebugReport(reports);
+
+ // location block
+ if (reports.mLocation.mValid) {
+ data.position.valid = true;
+ data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
+ data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
+ data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
+
+ data.position.speedMetersPerSec =
+ (double)(reports.mLocation.mLocation.speed);
+ data.position.bearingDegrees =
+ (double)(reports.mLocation.mLocation.bearing);
+ data.position.horizontalAccuracyMeters =
+ (double)(reports.mLocation.mLocation.accuracy);
+ data.position.verticalAccuracyMeters =
+ reports.mLocation.verticalAccuracyMeters;
+ data.position.speedAccuracyMetersPerSecond =
+ reports.mLocation.speedAccuracyMetersPerSecond;
+ data.position.bearingAccuracyDegrees =
+ reports.mLocation.bearingAccuracyDegrees;
+
+ timeval tv_now, tv_report;
+ tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec;
+ tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
+ gettimeofday(&tv_now, NULL);
+ data.position.ageSeconds =
+ (tv_now.tv_sec - tv_report.tv_sec) +
+ (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
+ }
+ else {
+ data.position.valid = false;
+ }
+
+ if (data.position.horizontalAccuracyMeters <= 0 ||
+ data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
+ data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
+ }
+ if (data.position.verticalAccuracyMeters <= 0 ||
+ data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
+ data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
+ }
+ if (data.position.speedAccuracyMetersPerSecond <= 0 ||
+ data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
+ data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
+ }
+ if (data.position.bearingAccuracyDegrees <= 0 ||
+ data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
+ data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
+ }
+
+ // time block
+ if (reports.mTime.mValid) {
+ data.time.timeEstimate = reports.mTime.timeEstimate;
+ data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
+ data.time.frequencyUncertaintyNsPerSec =
+ reports.mTime.frequencyUncertaintyNsPerSec;
+ }
+
+ if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
+ data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
+ }
+ if (data.time.timeUncertaintyNs <= 0) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
+ }
+ else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
+ data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
+ }
+ if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
+ data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
+ data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
+ }
+
+ // satellite data block
+ V2_0::IGnssDebug::SatelliteData s = { };
+ std::vector<V2_0::IGnssDebug::SatelliteData> s_array;
+
+ for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
+ memset(&s, 0, sizeof(s));
+ s.v1_0.svid = reports.mSatelliteInfo[i].svid;
+ convertGnssConstellationType(
+ reports.mSatelliteInfo[i].constellation, s.constellation);
+ convertGnssEphemerisType(
+ reports.mSatelliteInfo[i].mEphemerisType, s.v1_0.ephemerisType);
+ convertGnssEphemerisSource(
+ reports.mSatelliteInfo[i].mEphemerisSource, s.v1_0.ephemerisSource);
+ convertGnssEphemerisHealth(
+ reports.mSatelliteInfo[i].mEphemerisHealth, s.v1_0.ephemerisHealth);
+
+ s.v1_0.ephemerisAgeSeconds =
+ reports.mSatelliteInfo[i].ephemerisAgeSeconds;
+ s.v1_0.serverPredictionIsAvailable =
+ reports.mSatelliteInfo[i].serverPredictionIsAvailable;
+ s.v1_0.serverPredictionAgeSeconds =
+ reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
+
+ s_array.push_back(s);
+ }
+ data.satelliteDataArray = s_array;
+
+ // callback HIDL with collected debug data
+ _hidl_cb(data);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssDebug.h b/gps/android/2.1/GnssDebug.h
new file mode 100644
index 0000000..4eaf34a
--- /dev/null
+++ b/gps/android/2.1/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
+
+
+#include <android/hardware/gnss/2.0/IGnssDebug.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct Gnss;
+struct GnssDebug : public IGnssDebug {
+ GnssDebug(Gnss* gnss);
+ ~GnssDebug() {};
+
+ // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow
+ Return<void> getDebugData(getDebugData_cb _hidl_cb) override;
+ // Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow.
+ Return<void> getDebugData_2_0(getDebugData_2_0_cb _hidl_cb) override;
+
+private:
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSDEBUG_H
diff --git a/gps/android/2.1/GnssGeofencing.cpp b/gps/android/2.1/GnssGeofencing.cpp
new file mode 100644
index 0000000..0ca3e6d
--- /dev/null
+++ b/gps/android/2.1/GnssGeofencing.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include <log_util.h>
+#include <GeofenceAPIClient.h>
+#include "GnssGeofencing.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssGeofencing != nullptr) {
+ mGnssGeofencing->removeAllGeofences();
+ }
+}
+
+GnssGeofencing::GnssGeofencing() : mApi(nullptr) {
+ mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this);
+}
+
+GnssGeofencing::~GnssGeofencing() {
+ if (mApi != nullptr) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) {
+ if (mApi != nullptr) {
+ LOC_LOGd("mApi is NOT nullptr");
+ return Void();
+ }
+
+ mApi = new GeofenceAPIClient(callback);
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: failed to create mApi", __FUNCTION__);
+ }
+
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient);
+ }
+ mGnssGeofencingCbIface = callback;
+ if (mGnssGeofencingCbIface != nullptr) {
+ mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+ int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceAdd(
+ geofenceId,
+ latitudeDegrees,
+ longitudeDegrees,
+ radiusMeters,
+ static_cast<int32_t>(lastTransition),
+ monitorTransitions,
+ notificationResponsivenessMs,
+ unknownTimerMs);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofencePause(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceResume(geofenceId, monitorTransitions);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ } else {
+ mApi->geofenceRemove(geofenceId);
+ }
+ return Void();
+}
+
+Return<void> GnssGeofencing::removeAllGeofences() {
+ if (mApi == nullptr) {
+ LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__);
+ } else {
+ mApi->geofenceRemoveAll();
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssGeofencing.h b/gps/android/2.1/GnssGeofencing.h
new file mode 100644
index 0000000..1cdca12
--- /dev/null
+++ b/gps/android/2.1/GnssGeofencing.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
+
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class GeofenceAPIClient;
+struct GnssGeofencing : public IGnssGeofencing {
+ GnssGeofencing();
+ ~GnssGeofencing();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+ * These declarations were generated from IGnssGeofencing.hal.
+ */
+ Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override;
+ Return<void> addGeofence(int32_t geofenceId,
+ double latitudeDegrees,
+ double longitudeDegrees,
+ double radiusMeters,
+ IGnssGeofenceCallback::GeofenceTransition lastTransition,
+ int32_t monitorTransitions,
+ uint32_t notificationResponsivenessMs,
+ uint32_t unknownTimerMs) override;
+
+ Return<void> pauseGeofence(int32_t geofenceId) override;
+ Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override;
+ Return<void> removeGeofence(int32_t geofenceId) override;
+
+ private:
+ // This method is not part of the IGnss base class.
+ // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far.
+ Return<void> removeAllGeofences();
+
+ private:
+ struct GnssGeofencingDeathRecipient : hidl_death_recipient {
+ GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) :
+ mGnssGeofencing(gnssGeofencing) {
+ }
+ ~GnssGeofencingDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssGeofencing> mGnssGeofencing;
+ };
+
+ private:
+ sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr;
+ sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr;
+ GeofenceAPIClient* mApi = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSGEOFENCING_H
diff --git a/gps/android/2.1/GnssMeasurement.cpp b/gps/android/2.1/GnssMeasurement.cpp
new file mode 100644
index 0000000..af75802
--- /dev/null
+++ b/gps/android/2.1/GnssMeasurement.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssMeasurementInterface"
+
+#include <log_util.h>
+#include "GnssMeasurement.h"
+#include "MeasurementAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied(
+ uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+}
+
+GnssMeasurement::GnssMeasurement() {
+ mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this);
+ mApi = new MeasurementAPIClient();
+}
+
+GnssMeasurement::~GnssMeasurement() {
+ if (mApi) {
+ mApi->destroy();
+ mApi = nullptr;
+ }
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface = callback;
+ mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ return mApi->measurementSetCallback(callback);
+}
+
+void GnssMeasurement::clearInterfaces() {
+ if (mGnssMeasurementCbIface != nullptr) {
+ mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface = nullptr;
+ }
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ mGnssMeasurementCbIface_1_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ }
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ mGnssMeasurementCbIface_2_1->unlinkToDeath(mGnssMeasurementDeathRecipient);
+ mGnssMeasurementCbIface_2_1 = nullptr;
+ }
+}
+
+Return<void> GnssMeasurement::close() {
+ if (mApi == nullptr) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ clearInterfaces();
+ mApi->measurementClose();
+
+ return Void();
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_1_1 = callback;
+ mGnssMeasurementCbIface_1_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_1_1(callback, powerMode);
+}
+// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_0 = callback;
+ mGnssMeasurementCbIface_2_0->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_0(callback, powerMode);
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
+ const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+ Return<GnssMeasurement::GnssMeasurementStatus> ret =
+ IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC;
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__);
+ return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT;
+ }
+
+ if (callback == nullptr) {
+ LOC_LOGE("%s]: callback is nullptr", __FUNCTION__);
+ return ret;
+ }
+ if (nullptr == mApi) {
+ LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__);
+ return ret;
+ }
+
+ clearInterfaces();
+
+ mGnssMeasurementCbIface_2_1 = callback;
+ mGnssMeasurementCbIface_2_1->linkToDeath(mGnssMeasurementDeathRecipient, 0);
+
+ GnssPowerMode powerMode = enableFullTracking ?
+ GNSS_POWER_MODE_M1 : GNSS_POWER_MODE_M2;
+
+ return mApi->measurementSetCallback_2_1(callback, powerMode);
+
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssMeasurement.h b/gps/android/2.1/GnssMeasurement.h
new file mode 100644
index 0000000..2ac45c6
--- /dev/null
+++ b/gps/android/2.1/GnssMeasurement.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
+
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class MeasurementAPIClient;
+struct GnssMeasurement : public V2_1::IGnssMeasurement {
+ GnssMeasurement();
+ ~GnssMeasurement();
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+ * These declarations were generated from IGnssMeasurement.hal.
+ */
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+ Return<void> close() override;
+
+ // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+ // Methods from ::android::hardware::gnss::V2_1::IGnssMeasurement follow.
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
+ const sp<::android::hardware::gnss::V2_1::IGnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+
+ private:
+ struct GnssMeasurementDeathRecipient : hidl_death_recipient {
+ GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) :
+ mGnssMeasurement(gnssMeasurement) {
+ }
+ ~GnssMeasurementDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssMeasurement> mGnssMeasurement;
+ };
+
+ private:
+ sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1 = nullptr;
+ MeasurementAPIClient* mApi;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSMEASUREMENT_H
diff --git a/gps/android/2.1/GnssNi.cpp b/gps/android/2.1/GnssNi.cpp
new file mode 100644
index 0000000..ba5e8d9
--- /dev/null
+++ b/gps/android/2.1/GnssNi.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LocSvc_GnssNiInterface"
+
+#include <log_util.h>
+#include "Gnss.h"
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+void GnssNi::GnssNiDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ LOC_LOGE("%s] service died. cookie: %llu, who: %p",
+ __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
+ // we do nothing here
+ // Gnss::GnssDeathRecipient will stop the session
+}
+
+GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) {
+ mGnssNiDeathRecipient = new GnssNiDeathRecipient(this);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ mGnss->setGnssNiCb(callback);
+
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient);
+ }
+ mGnssNiCbIface = callback;
+ if (mGnssNiCbIface != nullptr) {
+ mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/);
+ }
+
+ return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) {
+ if (mGnss == nullptr) {
+ LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ GnssAPIClient* api = mGnss->getApi();
+ if (api == nullptr) {
+ LOC_LOGE("%s]: api is nullptr", __FUNCTION__);
+ return Void();
+ }
+
+ api->gnssNiRespond(notifId, userResponse);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssNi.h b/gps/android/2.1/GnssNi.h
new file mode 100644
index 0000000..9a8fb69
--- /dev/null
+++ b/gps/android/2.1/GnssNi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
+
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Gnss;
+struct GnssNi : public IGnssNi {
+ GnssNi(Gnss* gnss);
+ ~GnssNi() = default;
+
+ /*
+ * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+ * These declarations were generated from IGnssNi.hal.
+ */
+ Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+ Return<void> respond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+ private:
+ struct GnssNiDeathRecipient : hidl_death_recipient {
+ GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) {
+ }
+ ~GnssNiDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<GnssNi> mGnssNi;
+ };
+
+ private:
+ sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr;
+ sp<IGnssNiCallback> mGnssNiCbIface = nullptr;
+ Gnss* mGnss = nullptr;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V2_0_GNSSNI_H
diff --git a/gps/android/2.1/GnssVisibilityControl.cpp b/gps/android/2.1/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..5a8c697
--- /dev/null
+++ b/gps/android/2.1/GnssVisibilityControl.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "GnssVisibilityControl.h"
+#include <location_interface.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+static GnssVisibilityControl* spGnssVisibilityControl = nullptr;
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out);
+
+GnssVisibilityControl::GnssVisibilityControl(Gnss* gnss) : mGnss(gnss) {
+ spGnssVisibilityControl = this;
+}
+GnssVisibilityControl::~GnssVisibilityControl() {
+ spGnssVisibilityControl = nullptr;
+}
+
+void GnssVisibilityControl::nfwStatusCb(GnssNfwNotification notification) {
+ if (nullptr != spGnssVisibilityControl) {
+ spGnssVisibilityControl->statusCb(notification);
+ }
+}
+
+bool GnssVisibilityControl::isInEmergencySession() {
+ if (nullptr != spGnssVisibilityControl) {
+ return spGnssVisibilityControl->isE911Session();
+ }
+ return false;
+}
+
+static void convertGnssNfwNotification(GnssNfwNotification& in,
+ IGnssVisibilityControlCallback::NfwNotification& out)
+{
+ memset(&out, 0, sizeof(IGnssVisibilityControlCallback::NfwNotification));
+ out.proxyAppPackageName = in.proxyAppPackageName;
+ out.protocolStack = (IGnssVisibilityControlCallback::NfwProtocolStack)in.protocolStack;
+ out.otherProtocolStackName = in.otherProtocolStackName;
+ out.requestor = (IGnssVisibilityControlCallback::NfwRequestor)in.requestor;
+ out.requestorId = in.requestorId;
+ out.responseType = (IGnssVisibilityControlCallback::NfwResponseType)in.responseType;
+ out.inEmergencyMode = in.inEmergencyMode;
+ out.isCachedLocation = in.isCachedLocation;
+}
+
+void GnssVisibilityControl::statusCb(GnssNfwNotification notification) {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ IGnssVisibilityControlCallback::NfwNotification nfwNotification;
+
+ // Convert from one structure to another
+ convertGnssNfwNotification(notification, nfwNotification);
+
+ auto r = mGnssVisibilityControlCbIface->nfwNotifyCb(nfwNotification);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+bool GnssVisibilityControl::isE911Session() {
+
+ if (mGnssVisibilityControlCbIface != nullptr) {
+ auto r = mGnssVisibilityControlCbIface->isInEmergencySession();
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking NFW status cb %s", r.description().c_str());
+ return false;
+ } else {
+ return (r);
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ return false;
+ }
+}
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+
+ /* If the vector is empty we need to disable all NFW clients
+ If there is at least one app in the vector we need to enable
+ all NFW clients */
+ if (0 == proxyApps.size()) {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(false);
+ } else {
+ mGnss->getGnssInterface()->enableNfwLocationAccess(true);
+ }
+
+ return true;
+}
+/**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+Return<bool> GnssVisibilityControl::setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mGnssVisibilityControlCbIface = callback;
+
+ NfwCbInfo cbInfo = {};
+ cbInfo.visibilityControlCb = (void*)nfwStatusCb;
+ cbInfo.isInEmergencySession = (void*)isInEmergencySession;
+
+ mGnss->getGnssInterface()->nfwInit(cbInfo);
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/GnssVisibilityControl.h b/gps/android/2.1/GnssVisibilityControl.h
new file mode 100644
index 0000000..6794a64
--- /dev/null
+++ b/gps/android/2.1/GnssVisibilityControl.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+ GnssVisibilityControl(Gnss* gnss);
+ ~GnssVisibilityControl();
+
+ // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+ Return<bool> enableNfwLocationAccess(const hidl_vec<::android::hardware::hidl_string>& proxyApps) override;
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ Return<bool> setCallback(const ::android::sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback>& callback) override;
+
+ void statusCb(GnssNfwNotification notification);
+ bool isE911Session();
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void nfwStatusCb(GnssNfwNotification notification);
+ static bool isInEmergencySession();
+
+private:
+ Gnss* mGnss = nullptr;
+ sp<IGnssVisibilityControlCallback> mGnssVisibilityControlCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace visibility_control
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_0_GnssVisibilityControl_H
diff --git a/gps/android/2.1/MeasurementCorrections.cpp b/gps/android/2.1/MeasurementCorrections.cpp
new file mode 100644
index 0000000..f8f0803
--- /dev/null
+++ b/gps/android/2.1/MeasurementCorrections.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "LocSvc_MeasurementCorrectionsInterface"
+
+#include <log_util.h>
+#include "MeasurementCorrections.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+static MeasurementCorrections* spMeasurementCorrections = nullptr;
+
+void MeasurementCorrections::GnssMeasurementCorrectionsDeathRecipient::serviceDied(uint64_t cookie,
+ const wp<IBase>& who) {
+ LOC_LOGe("service died. cookie: %llu, who: %p", static_cast<unsigned long long>(cookie), &who);
+ // Gnss::GnssDeathrecipient will stop the session
+ // we inform the adapter that service has died
+ if (nullptr == spMeasurementCorrections) {
+ LOC_LOGe("spMeasurementCorrections is nullptr");
+ return;
+ }
+ if (nullptr == spMeasurementCorrections->mGnss ||
+ nullptr == spMeasurementCorrections->mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return;
+ }
+ spMeasurementCorrections->mGnss->getGnssInterface()->measCorrClose();
+}
+
+MeasurementCorrections::MeasurementCorrections(Gnss* gnss) : mGnss(gnss) {
+ mGnssMeasurementCorrectionsDeathRecipient = new GnssMeasurementCorrectionsDeathRecipient(this);
+ spMeasurementCorrections = this;
+}
+
+MeasurementCorrections::~MeasurementCorrections() {
+ spMeasurementCorrections = nullptr;
+}
+
+void MeasurementCorrections::measCorrSetCapabilitiesCb(
+ GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+ if (nullptr != spMeasurementCorrections) {
+ spMeasurementCorrections->setCapabilitiesCb(capabilities);
+ }
+}
+
+void MeasurementCorrections::setCapabilitiesCb(
+ GnssMeasurementCorrectionsCapabilitiesMask capabilities) {
+
+ if (mMeasurementCorrectionsCbIface != nullptr) {
+ uint32_t measCorrCapabilities = 0;
+
+ // Convert from one enum to another
+ if (capabilities & GNSS_MEAS_CORR_LOS_SATS) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::LOS_SATS;
+ }
+ if (capabilities & GNSS_MEAS_CORR_EXCESS_PATH_LENGTH) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::EXCESS_PATH_LENGTH;
+ }
+ if (capabilities & GNSS_MEAS_CORR_REFLECTING_PLANE) {
+ measCorrCapabilities |=
+ IMeasurementCorrectionsCallback::Capabilities::REFLECTING_PLANE;
+ }
+
+ auto r = mMeasurementCorrectionsCbIface->setCapabilitiesCb(measCorrCapabilities);
+ if (!r.isOk()) {
+ LOC_LOGw("Error invoking setCapabilitiesCb %s", r.description().c_str());
+ }
+ } else {
+ LOC_LOGw("setCallback has not been called yet");
+ }
+}
+
+Return<bool> MeasurementCorrections::setCorrections(
+ const MeasurementCorrectionsV1_0& corrections) {
+
+ GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+ V2_1::implementation::convertMeasurementCorrections(corrections, gnssMeasurementCorrections);
+
+ return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCorrections_1_1(
+ const MeasurementCorrectionsV1_1& corrections) {
+
+ GnssMeasurementCorrections gnssMeasurementCorrections = {};
+
+ V2_1::implementation::convertMeasurementCorrections(
+ corrections.v1_0, gnssMeasurementCorrections);
+
+ gnssMeasurementCorrections.hasEnvironmentBearing = corrections.hasEnvironmentBearing;
+ gnssMeasurementCorrections.environmentBearingDegrees =
+ corrections.environmentBearingDegrees;
+ gnssMeasurementCorrections.environmentBearingUncertaintyDegrees =
+ corrections.environmentBearingUncertaintyDegrees;
+
+ for (int i = 0; i < corrections.satCorrections.size(); i++) {
+ GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+ V2_1::implementation::convertSingleSatCorrections(
+ corrections.satCorrections[i].v1_0, gnssSingleSatCorrection);
+ switch (corrections.satCorrections[i].constellation) {
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GPS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GPS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::SBAS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_SBAS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GLONASS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GLONASS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::QZSS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_QZSS;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::BEIDOU):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_BEIDOU;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::GALILEO):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_GALILEO;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::IRNSS):
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_NAVIC;
+ break;
+ case (::android::hardware::gnss::V2_0::GnssConstellationType::UNKNOWN):
+ default:
+ gnssSingleSatCorrection.svType = GNSS_SV_TYPE_UNKNOWN;
+ break;
+ }
+ gnssMeasurementCorrections.satCorrections.push_back(gnssSingleSatCorrection);
+ }
+
+ return mGnss->getGnssInterface()->measCorrSetCorrections(gnssMeasurementCorrections);
+}
+
+Return<bool> MeasurementCorrections::setCallback(
+ const sp<V1_0::IMeasurementCorrectionsCallback>& callback) {
+
+ if (nullptr == mGnss || nullptr == mGnss->getGnssInterface()) {
+ LOC_LOGe("Null GNSS interface");
+ return false;
+ }
+ mMeasurementCorrectionsCbIface = callback;
+
+ return mGnss->getGnssInterface()->measCorrInit(measCorrSetCapabilitiesCb);
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/MeasurementCorrections.h b/gps/android/2.1/MeasurementCorrections.h
new file mode 100644
index 0000000..92fcc6a
--- /dev/null
+++ b/gps/android/2.1/MeasurementCorrections.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+#define ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
+
+#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrectionsCallback.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <gps_extended_c.h>
+#include <location_interface.h>
+#include "Gnss.h"
+#include <LocationUtil.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace measurement_corrections {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+using ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using MeasurementCorrectionsV1_1 =
+ ::android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
+
+struct MeasurementCorrections : public V1_1::IMeasurementCorrections {
+ MeasurementCorrections(Gnss* gnss);
+ ~MeasurementCorrections();
+
+ Return<bool> setCorrections(const MeasurementCorrectionsV1_0& corrections) override;
+
+ // Methods from
+ // ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections follow.
+ Return<bool> setCorrections_1_1(const MeasurementCorrectionsV1_1& corrections);
+
+ Return<bool> setCallback(const sp<IMeasurementCorrectionsCallback>& callback) override;
+
+ void setCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+ /* Data call setup callback passed down to GNSS HAL implementation */
+ static void measCorrSetCapabilitiesCb(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+private:
+ struct GnssMeasurementCorrectionsDeathRecipient : hidl_death_recipient {
+ GnssMeasurementCorrectionsDeathRecipient(
+ sp<MeasurementCorrections> gnssMeasurementCorrections) :
+ mGnssMeasurementCorrections(gnssMeasurementCorrections) {
+ }
+ ~GnssMeasurementCorrectionsDeathRecipient() = default;
+ virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
+ sp<MeasurementCorrections> mGnssMeasurementCorrections;
+ };
+ Gnss* mGnss = nullptr;
+ sp<GnssMeasurementCorrectionsDeathRecipient> mGnssMeasurementCorrectionsDeathRecipient =
+ nullptr;
+ sp<IMeasurementCorrectionsCallback> mMeasurementCorrectionsCbIface = nullptr;
+};
+
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace measurement_corrections
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GNSS_V1_1_MeasurementCorrections_H
diff --git a/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc
new file mode 100644
index 0000000..19e32c4
--- /dev/null
+++ b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.rc
@@ -0,0 +1,4 @@
+service gnss_service /vendor/bin/hw/android.hardware.gnss@2.1-service-qti
+ class hal
+ user gps
+ group system gps radio vendor_qti_diag
diff --git a/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml
new file mode 100755
index 0000000..842fb6e
--- /dev/null
+++ b/gps/android/2.1/android.hardware.gnss@2.1-service-qti.xml
@@ -0,0 +1,36 @@
+<!-- Copyright (c) 2020, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.1::IGnss/default</fqname>
+ <fqname>@2.1::IGnss/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/gps/android/2.1/location_api/BatchingAPIClient.cpp b/gps/android/2.1/location_api/BatchingAPIClient.cpp
new file mode 100644
index 0000000..00d2ed9
--- /dev/null
+++ b/gps/android/2.1/location_api/BatchingAPIClient.cpp
@@ -0,0 +1,251 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAPIClient"
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "BatchingAPIClient.h"
+
+#include "limits.h"
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::IGnssBatching;
+using ::android::hardware::gnss::V2_0::IGnssBatchingCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask);
+
+BatchingAPIClient::BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks(callback);
+}
+
+BatchingAPIClient::BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssBatchingCbIface(nullptr),
+ mDefaultId(UINT_MAX),
+ mLocationCapabilitiesMask(0),
+ mGnssBatchingCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ gnssUpdateCallbacks_2_0(callback);
+}
+
+BatchingAPIClient::~BatchingAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+int BatchingAPIClient::getBatchSize()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ return locAPIGetBatchSize();
+}
+
+void BatchingAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.batchingCb = [this](size_t count, Location* location,
+ BatchingOptions batchOptions) {
+ onBatchingCb(count, location, batchOptions);
+ };
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback)
+{
+ mMutex.lock();
+ mGnssBatchingCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ if (mGnssBatchingCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+int BatchingAPIClient::startSession(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts)
+{
+ LOC_LOGD("%s]: (%lld %d)", __FUNCTION__,
+ static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags));
+ int retVal = -1;
+ LocationOptions options;
+ convertBatchOption(opts, options, mLocationCapabilitiesMask);
+
+ uint32_t mode = 0;
+ if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) {
+ mode = SESSION_MODE_ON_FULL;
+ }
+ if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+int BatchingAPIClient::stopSession()
+{
+ LOC_LOGD("%s]: ", __FUNCTION__);
+ int retVal = -1;
+ if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) {
+ retVal = 1;
+ }
+ return retVal;
+}
+
+void BatchingAPIClient::getBatchedLocation(int last_n_locations)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations);
+ locAPIGetBatchedLocations(mDefaultId, last_n_locations);
+}
+
+void BatchingAPIClient::flushBatchedLocations()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ locAPIGetBatchedLocations(mDefaultId, SIZE_MAX);
+}
+
+void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+}
+
+void BatchingAPIClient::onBatchingCb(size_t count, Location* location,
+ BatchingOptions /*batchOptions*/)
+{
+ mMutex.lock();
+ auto gnssBatchingCbIface(mGnssBatchingCbIface);
+ auto gnssBatchingCbIface_2_0(mGnssBatchingCbIface_2_0);
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count);
+ if (gnssBatchingCbIface_2_0 != nullptr && count > 0) {
+ hidl_vec<V2_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface_2_0->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssBatchingCbIface != nullptr && count > 0) {
+ hidl_vec<V1_0::GnssLocation> locationVec;
+ locationVec.resize(count);
+ for (size_t i = 0; i < count; i++) {
+ convertGnssLocation(location[i], locationVec[i]);
+ }
+ auto r = gnssBatchingCbIface->gnssLocationBatchCb(locationVec);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationBatchCb 1.0 description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out,
+ LocationCapabilitiesMask mask)
+{
+ memset(&out, 0, sizeof(LocationOptions));
+ out.size = sizeof(LocationOptions);
+ out.minInterval = (uint32_t)(in.periodNanos / 1000000L);
+ out.minDistance = 0;
+ out.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ out.mode = GNSS_SUPL_MODE_MSA;
+ if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ out.mode = GNSS_SUPL_MODE_MSB;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/BatchingAPIClient.h b/gps/android/2.1/location_api/BatchingAPIClient.h
new file mode 100755
index 0000000..08d7d23
--- /dev/null
+++ b/gps/android/2.1/location_api/BatchingAPIClient.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef BATCHING_API_CLINET_H
+#define BATCHING_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatchingCallback.h>
+#include <pthread.h>
+
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+class BatchingAPIClient : public LocationAPIClientBase
+{
+public:
+ BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback);
+ BatchingAPIClient(const sp<V2_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssBatchingCallback>& callback);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssBatchingCallback>& callback);
+ int getBatchSize();
+ int startSession(const V1_0::IGnssBatching::Options& options);
+ int updateSessionOptions(const V1_0::IGnssBatching::Options& options);
+ int stopSession();
+ void getBatchedLocation(int last_n_locations);
+ void flushBatchedLocations();
+
+ inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; }
+
+ // callbacks
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final;
+
+private:
+ ~BatchingAPIClient();
+
+ void setCallbacks();
+ std::mutex mMutex;
+ sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface;
+ uint32_t mDefaultId;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ sp<V2_0::IGnssBatchingCallback> mGnssBatchingCbIface_2_0;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // BATCHING_API_CLINET_H
diff --git a/gps/android/2.1/location_api/GeofenceAPIClient.cpp b/gps/android/2.1/location_api/GeofenceAPIClient.cpp
new file mode 100755
index 0000000..6e63465
--- /dev/null
+++ b/gps/android/2.1/location_api/GeofenceAPIClient.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GeofenceApiClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GeofenceAPIClient.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::GnssLocation;
+
+GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
+ LocationAPIClientBase(),
+ mGnssGeofencingCbIface(callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+
+ locationCallbacks.geofenceBreachCb = nullptr;
+ if (mGnssGeofencingCbIface != nullptr) {
+ locationCallbacks.geofenceBreachCb =
+ [this](GeofenceBreachNotification geofenceBreachNotification) {
+ onGeofenceBreachCb(geofenceBreachNotification);
+ };
+
+ locationCallbacks.geofenceStatusCb =
+ [this](GeofenceStatusNotification geofenceStatusNotification) {
+ onGeofenceStatusCb(geofenceStatusNotification);
+ };
+ }
+
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
+{
+ LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
+ geofence_id, latitude, longitude, radius_meters,
+ last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
+
+ GeofenceOption options;
+ memset(&options, 0, sizeof(GeofenceOption));
+ options.size = sizeof(GeofenceOption);
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT;
+ options.responsiveness = notification_responsiveness_ms;
+
+ GeofenceInfo data;
+ data.size = sizeof(GeofenceInfo);
+ data.latitude = latitude;
+ data.longitude = longitude;
+ data.radius = radius_meters;
+
+ LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ onAddGeofencesCb(1, &err, &geofence_id);
+ }
+}
+
+void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIPauseGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
+ GeofenceBreachTypeMask mask = 0;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
+ mask |= GEOFENCE_BREACH_ENTER_BIT;
+ if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
+ mask |= GEOFENCE_BREACH_EXIT_BIT;
+ locAPIResumeGeofences(1, &geofence_id, &mask);
+}
+
+void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
+ locAPIRemoveGeofences(1, &geofence_id);
+}
+
+void GeofenceAPIClient::geofenceRemoveAll()
+{
+ LOC_LOGD("%s]", __FUNCTION__);
+ // TODO locAPIRemoveAllGeofences();
+}
+
+// callbacks
+void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceBreachNotification.count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
+ GnssLocation gnssLocation;
+ convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
+
+ IGnssGeofenceCallback::GeofenceTransition transition;
+ if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
+ transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
+ else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
+ transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
+ else {
+ // continue with other breach if transition is
+ // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
+ continue;
+ }
+
+ auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+ geofenceBreachNotification.ids[i], gnssLocation, transition,
+ static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp));
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
+ if (mGnssGeofencingCbIface != nullptr) {
+ IGnssGeofenceCallback::GeofenceAvailability status =
+ IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
+ if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
+ status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
+ }
+ GnssLocation gnssLocation;
+ memset(&gnssLocation, 0, sizeof(GnssLocation));
+ auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
+{
+ LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
+ if (mGnssGeofencingCbIface != nullptr) {
+ for (size_t i = 0; i < count; i++) {
+ IGnssGeofenceCallback::GeofenceStatus status =
+ IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
+ if (errors[i] == LOCATION_ERROR_SUCCESS)
+ status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
+ else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
+ status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
+ auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/GeofenceAPIClient.h b/gps/android/2.1/location_api/GeofenceAPIClient.h
new file mode 100755
index 0000000..9ed289f
--- /dev/null
+++ b/gps/android/2.1/location_api/GeofenceAPIClient.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GEOFENCE_API_CLINET_H
+#define GEOFENCE_API_CLINET_H
+
+
+#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GeofenceAPIClient : public LocationAPIClientBase
+{
+public:
+ GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback);
+
+ void geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int32_t last_transition, int32_t monitor_transitions,
+ uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms);
+ void geofencePause(uint32_t geofence_id);
+ void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions);
+ void geofenceRemove(uint32_t geofence_id);
+ void geofenceRemoveAll();
+
+ // callbacks
+ void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final;
+ void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final;
+ void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+ void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final;
+
+private:
+ virtual ~GeofenceAPIClient() = default;
+
+ sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GEOFENCE_API_CLINET_H
diff --git a/gps/android/2.1/location_api/GnssAPIClient.cpp b/gps/android/2.1/location_api/GnssAPIClient.cpp
new file mode 100644
index 0000000..07f617d
--- /dev/null
+++ b/gps/android/2.1/location_api/GnssAPIClient.cpp
@@ -0,0 +1,864 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAPIClient"
+#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours
+
+#include <inttypes.h>
+#include <log_util.h>
+#include <loc_cfg.h>
+
+#include "LocationUtil.h"
+#include "GnssAPIClient.h"
+#include <LocContext.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_1::IGnss;
+using ::android::hardware::gnss::V2_1::IGnssCallback;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::gnss::V2_0::GnssLocation;
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out);
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out);
+
+GnssAPIClient::GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks(gpsCb, niCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_0(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks_2_0(gpsCb);
+}
+
+GnssAPIClient::GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb) :
+ LocationAPIClientBase(),
+ mGnssCbIface(nullptr),
+ mGnssNiCbIface(nullptr),
+ mControlClient(new LocationAPIControlClient()),
+ mLocationCapabilitiesMask(0),
+ mLocationCapabilitiesCached(false),
+ mTracking(false),
+ mGnssCbIface_2_1(nullptr)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ initLocationOptions();
+ gnssUpdateCallbacks_2_1(gpsCb);
+}
+
+GnssAPIClient::~GnssAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient) {
+ delete mControlClient;
+ mControlClient = nullptr;
+ }
+}
+
+void GnssAPIClient::initLocationOptions()
+{
+ // set default LocationOptions.
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = 1000;
+ mTrackingOptions.minDistance = 0;
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+}
+
+void GnssAPIClient::setCallbacks()
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.trackingCb = [this](Location location) {
+ onTrackingCb(location);
+ };
+
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ if (mGnssNiCbIface != nullptr) {
+ loc_core::ContextBase* context =
+ loc_core::LocContext::getLocContext(loc_core::LocContext::mLocationHalName);
+ if (!context->hasAgpsExtendedCapabilities()) {
+ LOC_LOGD("Registering NI CB");
+ locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotify) {
+ onGnssNiCb(id, gnssNiNotify);
+ };
+ }
+ }
+
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
+ onGnssSvCb(gnssSvNotification);
+ };
+
+ locationCallbacks.gnssNmeaCb = nullptr;
+ locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
+ onGnssNmeaCb(gnssNmeaNotification);
+ };
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+
+ locAPISetCallbacks(locationCallbacks);
+}
+
+// for GpsInterface
+void GnssAPIClient::gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<IGnssNiCallback>& niCb)
+{
+ LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
+
+ mMutex.lock();
+ mGnssCbIface = gpsCb;
+ mGnssNiCbIface = niCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr) {
+ setCallbacks();
+ }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ mMutex.lock();
+ mGnssCbIface_2_0 = gpsCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface_2_0 != nullptr) {
+ setCallbacks();
+ }
+}
+
+void GnssAPIClient::gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &gpsCb);
+
+ mMutex.lock();
+ mGnssCbIface_2_1 = gpsCb;
+ mMutex.unlock();
+
+ if (mGnssCbIface_2_1 != nullptr) {
+ setCallbacks();
+ }
+}
+
+bool GnssAPIClient::gnssStart()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = true;
+ mMutex.unlock();
+
+ bool retVal = true;
+ locAPIStartTracking(mTrackingOptions);
+ return retVal;
+}
+
+bool GnssAPIClient::gnssStop()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+
+ mMutex.lock();
+ mTracking = false;
+ mMutex.unlock();
+
+ bool retVal = true;
+ locAPIStopTracking();
+ return retVal;
+}
+
+bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
+ IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__,
+ (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters,
+ preferredTimeMs, (int)powerMode, timeBetweenMeasurement);
+ bool retVal = true;
+ memset(&mTrackingOptions, 0, sizeof(TrackingOptions));
+ mTrackingOptions.size = sizeof(TrackingOptions);
+ mTrackingOptions.minInterval = minIntervalMs;
+ if (IGnss::GnssPositionMode::MS_ASSISTED == mode ||
+ IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) {
+ // We set a very large interval to simulate SINGLE mode. Once we report a fix,
+ // the caller should take the responsibility to stop the session.
+ // For MSA, we always treat it as SINGLE mode.
+ mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC;
+ }
+ if (mode == IGnss::GnssPositionMode::STANDALONE)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE;
+ else if (mode == IGnss::GnssPositionMode::MS_BASED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSB;
+ else if (mode == IGnss::GnssPositionMode::MS_ASSISTED)
+ mTrackingOptions.mode = GNSS_SUPL_MODE_MSA;
+ else {
+ LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode);
+ retVal = false;
+ }
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ mTrackingOptions.powerMode = powerMode;
+ mTrackingOptions.tbm = timeBetweenMeasurement;
+ }
+ locAPIUpdateTrackingOptions(mTrackingOptions);
+ return retVal;
+}
+
+// for GpsNiInterface
+void GnssAPIClient::gnssNiRespond(int32_t notifId,
+ IGnssNiCallback::GnssUserResponseType userResponse)
+{
+ LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
+ GnssNiResponse data;
+ switch (userResponse) {
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT:
+ data = GNSS_NI_RESPONSE_ACCEPT;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY:
+ data = GNSS_NI_RESPONSE_DENY;
+ break;
+ case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP:
+ data = GNSS_NI_RESPONSE_NO_RESPONSE;
+ break;
+ default:
+ data = GNSS_NI_RESPONSE_IGNORE;
+ break;
+ }
+
+ locAPIGnssNiResponse(notifId, data);
+}
+
+// these apis using LocationAPIControlClient
+void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
+{
+ LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ GnssAidingData data;
+ memset(&data, 0, sizeof (GnssAidingData));
+ data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT |
+ GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT;
+ data.posEngineMask = STANDARD_POSITIONING_ENGINE;
+
+ if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
+ data.deleteAll = true;
+ else {
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
+ data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT;
+ if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
+ data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT;
+ }
+ mControlClient->locAPIGnssDeleteAidingData(data);
+}
+
+void GnssAPIClient::gnssEnable(LocationTechnologyType techType)
+{
+ LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIEnable(techType);
+}
+
+void GnssAPIClient::gnssDisable()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIDisable();
+}
+
+void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
+{
+ LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
+ if (mControlClient == nullptr) {
+ return;
+ }
+ mControlClient->locAPIGnssUpdateConfig(gnssConfig);
+}
+
+void GnssAPIClient::requestCapabilities() {
+ // only send capablities if it's already cached, otherwise the first time LocationAPI
+ // is initialized, capabilities will be sent by LocationAPI
+ if (mLocationCapabilitiesCached) {
+ onCapabilitiesCb(mLocationCapabilitiesMask);
+ }
+}
+
+// callbacks
+void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
+{
+ LOC_LOGD("%s]: (%" PRIu64 ")", __FUNCTION__, capabilitiesMask);
+ mLocationCapabilitiesMask = capabilitiesMask;
+ mLocationCapabilitiesCached = true;
+
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_1 != nullptr ||gnssCbIface_2_0 != nullptr || gnssCbIface != nullptr) {
+
+ uint32_t antennaInfoVectorSize = 0;
+ uint32_t data = 0;
+ loc_param_s_type ant_info_vector_table[] =
+ {
+ { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
+ };
+ UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
+
+ if (0 != antennaInfoVectorSize) {
+ data |= V2_1::IGnssCallback::Capabilities::ANTENNA_INFO;
+ }
+
+ if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
+ (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
+ data |= IGnssCallback::Capabilities::SCHEDULING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
+ data |= V1_0::IGnssCallback::Capabilities::GEOFENCING;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
+ data |= V1_0::IGnssCallback::Capabilities::MEASUREMENTS;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
+ data |= IGnssCallback::Capabilities::MSB;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
+ data |= IGnssCallback::Capabilities::MSA;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT)
+ data |= IGnssCallback::Capabilities::LOW_POWER_MODE;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT)
+ data |= IGnssCallback::Capabilities::SATELLITE_BLACKLIST;
+ if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT)
+ data |= V2_0::IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS;
+
+ IGnssCallback::GnssSystemInfo gnssInfo = { .yearOfHw = 2015 };
+
+ if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
+ gnssInfo.yearOfHw++; // 2016
+ if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) {
+ gnssInfo.yearOfHw++; // 2017
+ if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT ||
+ capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) {
+ gnssInfo.yearOfHw++; // 2018
+ if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) {
+ gnssInfo.yearOfHw++; // 2019
+ if (capabilitiesMask & LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT) {
+ gnssInfo.yearOfHw++; // 2020
+ }
+ }
+ }
+ }
+ }
+ LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
+
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssSetCapabilitiesCb_2_1(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_1 description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssSetCapabilitiesCb_2_0(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitiesCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssSetCapabilitesCb(data);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+
+ }
+
+}
+
+void GnssAPIClient::onTrackingCb(Location location)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ bool isTracking = mTracking;
+ mMutex.unlock();
+
+ LOC_LOGD("%s]: (flags: %02x isTracking: %d)", __FUNCTION__, location.flags, isTracking);
+
+ if (!isTracking) {
+ return;
+ }
+
+ if (gnssCbIface_2_1 != nullptr) {
+ V2_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface_2_1->gnssLocationCb_2_0(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ V2_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface_2_0->gnssLocationCb_2_0(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::GnssLocation gnssLocation;
+ convertGnssLocation(location, gnssLocation);
+ auto r = gnssCbIface->gnssLocationCb(gnssLocation);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssLocationCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else {
+ LOC_LOGW("%s] No GNSS Interface ready for gnssLocationCb ", __FUNCTION__);
+ }
+
+}
+
+void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
+{
+ LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
+ mMutex.lock();
+ auto gnssNiCbIface(mGnssNiCbIface);
+ mMutex.unlock();
+
+ if (gnssNiCbIface == nullptr) {
+ LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
+ return;
+ }
+
+ IGnssNiCallback::GnssNiNotification notificationGnss = {};
+
+ notificationGnss.notificationId = id;
+
+ if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
+ else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL)
+ notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL;
+
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY;
+ if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT)
+ notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE;
+
+ notificationGnss.timeoutSec = gnssNiNotification.timeout;
+
+ if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
+ else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
+ gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
+ notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
+
+ notificationGnss.requestorId = gnssNiNotification.requestor;
+
+ notificationGnss.notificationMessage = gnssNiNotification.message;
+
+ if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.requestorIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
+ else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
+ notificationGnss.notificationIdEncoding =
+ IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
+
+ gnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
+{
+ LOC_LOGD("%s]: (count: %u)", __FUNCTION__, gnssSvNotification.count);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface_2_1 != nullptr) {
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo> svInfoList;
+ convertGnssSvStatus(gnssSvNotification, svInfoList);
+ auto r = gnssCbIface_2_1->gnssSvStatusCb_2_1(svInfoList);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb_2_1 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo> svInfoList;
+ convertGnssSvStatus(gnssSvNotification, svInfoList);
+ auto r = gnssCbIface_2_0->gnssSvStatusCb_2_0(svInfoList);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb_2_0 description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ V1_0::IGnssCallback::GnssSvStatus svStatus;
+ convertGnssSvStatus(gnssSvNotification, svStatus);
+ auto r = gnssCbIface->gnssSvStatusCb(svStatus);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssSvStatusCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+}
+
+void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
+{
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (gnssCbIface != nullptr || gnssCbIface_2_0 != nullptr| gnssCbIface_2_1 != nullptr) {
+ const std::string s(gnssNmeaNotification.nmea);
+ std::stringstream ss(s);
+ std::string each;
+ while(std::getline(ss, each, '\n')) {
+ each += '\n';
+ android::hardware::hidl_string nmeaString;
+ nmeaString.setToExternal(each.c_str(), each.length());
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssCbIface_2_1 nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssCbIface_2_0 nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssNmeaCb(
+ static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s",
+ __func__, gnssNmeaNotification.nmea, gnssNmeaNotification.length,
+ r.description().c_str());
+ }
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStartTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+void GnssAPIClient::onStopTrackingCb(LocationError error)
+{
+ LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
+ mMutex.lock();
+ auto gnssCbIface(mGnssCbIface);
+ auto gnssCbIface_2_0(mGnssCbIface_2_0);
+ auto gnssCbIface_2_1(mGnssCbIface_2_1);
+ mMutex.unlock();
+
+ if (error == LOCATION_ERROR_SUCCESS) {
+ if (gnssCbIface_2_1 != nullptr) {
+ auto r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_1->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssCbIface_2_0 != nullptr) {
+ auto r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface_2_0->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb 2_0 ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+
+ } else if (gnssCbIface != nullptr) {
+ auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s",
+ __func__, r.description().c_str());
+ }
+ r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in, V1_0::IGnssCallback::GnssSvStatus& out)
+{
+ memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
+ out.numSvs = in.count;
+ if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.",
+ __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT);
+ out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.numSvs; i++) {
+ convertGnssSvid(in.gnssSvs[i], out.gnssSvList[i].svid);
+ convertGnssConstellationType(in.gnssSvs[i].type, out.gnssSvList[i].constellation);
+ out.gnssSvList[i].cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out.gnssSvList[i].elevationDegrees = in.gnssSvs[i].elevation;
+ out.gnssSvList[i].azimuthDegrees = in.gnssSvs[i].azimuth;
+ out.gnssSvList[i].carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out.gnssSvList[i].svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out.gnssSvList[i].svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_0::IGnssCallback::GnssSvInfo>& out)
+{
+ out.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssSvid(in.gnssSvs[i], out[i].v1_0.svid);
+ out[i].v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out[i].v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+ out[i].v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+ out[i].v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out[i].v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out[i].v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+ convertGnssConstellationType(in.gnssSvs[i].type, out[i].constellation);
+ }
+}
+
+static void convertGnssSvStatus(GnssSvNotification& in,
+ hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& out)
+{
+ out.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssSvid(in.gnssSvs[i], out[i].v2_0.v1_0.svid);
+ out[i].v2_0.v1_0.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
+ out[i].v2_0.v1_0.elevationDegrees = in.gnssSvs[i].elevation;
+ out[i].v2_0.v1_0.azimuthDegrees = in.gnssSvs[i].azimuth;
+ out[i].v2_0.v1_0.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz;
+ out[i].v2_0.v1_0.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT)
+ out[i].v2_0.v1_0.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY;
+
+ convertGnssConstellationType(in.gnssSvs[i].type, out[i].v2_0.constellation);
+ out[i].basebandCN0DbHz = in.gnssSvs[i].basebandCarrierToNoiseDbHz;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/GnssAPIClient.h b/gps/android/2.1/location_api/GnssAPIClient.h
new file mode 100755
index 0000000..c4dbe9a
--- /dev/null
+++ b/gps/android/2.1/location_api/GnssAPIClient.h
@@ -0,0 +1,118 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GNSS_API_CLINET_H
+#define GNSS_API_CLINET_H
+
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <android/hardware/gnss/2.1/IGnssCallback.h>
+#include <LocationAPIClientBase.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class GnssAPIClient : public LocationAPIClientBase
+{
+public:
+ GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ GnssAPIClient(const sp<V2_0::IGnssCallback>& gpsCb);
+ GnssAPIClient(const sp<V2_1::IGnssCallback>& gpsCb);
+ GnssAPIClient(const GnssAPIClient&) = delete;
+ GnssAPIClient& operator=(const GnssAPIClient&) = delete;
+
+ // for GpsInterface
+ void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb,
+ const sp<V1_0::IGnssNiCallback>& niCb);
+ void gnssUpdateCallbacks_2_0(const sp<V2_0::IGnssCallback>& gpsCb);
+ void gnssUpdateCallbacks_2_1(const sp<V2_1::IGnssCallback>& gpsCb);
+ bool gnssStart();
+ bool gnssStop();
+ bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode,
+ V1_0::IGnss::GnssPositionRecurrence recurrence,
+ uint32_t minIntervalMs,
+ uint32_t preferredAccuracyMeters,
+ uint32_t preferredTimeMs,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = 0);
+
+ // for GpsNiInterface
+ void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse);
+
+ // these apis using LocationAPIControlClient
+ void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags);
+ void gnssEnable(LocationTechnologyType techType);
+ void gnssDisable();
+ void gnssConfigurationUpdate(const GnssConfig& gnssConfig);
+
+ inline LocationCapabilitiesMask gnssGetCapabilities() const {
+ return mLocationCapabilitiesMask;
+ }
+ void requestCapabilities();
+
+ // callbacks we are interested in
+ void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final;
+ void onTrackingCb(Location location) final;
+ void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final;
+ void onGnssSvCb(GnssSvNotification gnssSvNotification) final;
+ void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final;
+
+ void onStartTrackingCb(LocationError error) final;
+ void onStopTrackingCb(LocationError error) final;
+
+private:
+ virtual ~GnssAPIClient();
+ void setCallbacks();
+ void initLocationOptions();
+
+ sp<V1_0::IGnssCallback> mGnssCbIface;
+ sp<V1_0::IGnssNiCallback> mGnssNiCbIface;
+ std::mutex mMutex;
+ LocationAPIControlClient* mControlClient;
+ LocationCapabilitiesMask mLocationCapabilitiesMask;
+ bool mLocationCapabilitiesCached;
+ TrackingOptions mTrackingOptions;
+ bool mTracking;
+ sp<V2_0::IGnssCallback> mGnssCbIface_2_0;
+ sp<V2_1::IGnssCallback> mGnssCbIface_2_1;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // GNSS_API_CLINET_H
diff --git a/gps/android/2.1/location_api/LocationUtil.cpp b/gps/android/2.1/location_api/LocationUtil.cpp
new file mode 100644
index 0000000..5154e70
--- /dev/null
+++ b/gps/android/2.1/location_api/LocationUtil.cpp
@@ -0,0 +1,405 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <LocationUtil.h>
+#include <log_util.h>
+#include <inttypes.h>
+#include <loc_misc_utils.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V2_0::GnssLocation;
+using ::android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
+using ::android::hardware::gnss::V2_0::GnssConstellationType;
+using ::android::hardware::gnss::V1_0::GnssLocationFlags;
+using ::android::hardware::gnss::measurement_corrections::V1_0::GnssSingleSatCorrectionFlags;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V1_0::GnssLocation));
+ if (in.flags & LOCATION_HAS_LAT_LONG_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG;
+ out.latitudeDegrees = in.latitude;
+ out.longitudeDegrees = in.longitude;
+ }
+ if (in.flags & LOCATION_HAS_ALTITUDE_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE;
+ out.altitudeMeters = in.altitude;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED;
+ out.speedMetersPerSec = in.speed;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING;
+ out.bearingDegrees = in.bearing;
+ }
+ if (in.flags & LOCATION_HAS_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY;
+ out.horizontalAccuracyMeters = in.accuracy;
+ }
+ if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY;
+ out.verticalAccuracyMeters = in.verticalAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY;
+ out.speedAccuracyMetersPerSecond = in.speedAccuracy;
+ }
+ if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) {
+ out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY;
+ out.bearingAccuracyDegrees = in.bearingAccuracy;
+ }
+
+ out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp);
+}
+
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out)
+{
+ memset(&out, 0, sizeof(V2_0::GnssLocation));
+ convertGnssLocation(in, out.v1_0);
+
+ if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ out.elapsedRealtime.timestampNs = in.elapsedRealTime;
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+ LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 ""
+ " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 ""
+ " out.elapsedRealtime.flags=0x%X",
+ out.elapsedRealtime.timestampNs,
+ out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags);
+ }
+}
+
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = in.latitudeDegrees;
+ out.longitude = in.longitudeDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = in.altitudeMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = in.speedMetersPerSec;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = in.bearingDegrees;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = in.horizontalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = in.verticalAccuracyMeters;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = in.speedAccuracyMetersPerSecond;
+ }
+ if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = in.bearingAccuracyDegrees;
+ }
+
+ out.timestamp = static_cast<uint64_t>(in.timestamp);
+}
+
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out)
+{
+ memset(&out, 0, sizeof(out));
+ convertGnssLocation(in.v1_0, out);
+}
+
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V1_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V1_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V1_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V1_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V1_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V1_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V1_0::GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out)
+{
+ switch(in) {
+ case GNSS_SV_TYPE_GPS:
+ out = V2_0::GnssConstellationType::GPS;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = V2_0::GnssConstellationType::SBAS;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ out = V2_0::GnssConstellationType::GLONASS;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = V2_0::GnssConstellationType::QZSS;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = V2_0::GnssConstellationType::BEIDOU;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = V2_0::GnssConstellationType::GALILEO;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = V2_0::GnssConstellationType::IRNSS;
+ break;
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ out = V2_0::GnssConstellationType::UNKNOWN;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssSv& in, int16_t& out)
+{
+ switch (in.type) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out)
+{
+ switch (in.svType) {
+ case GNSS_SV_TYPE_GPS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (!isGloSlotUnknown(in.svId)) { // OSN is known
+ out = in.svId - GLO_SV_PRN_MIN + 1;
+ } else { // OSN is not known, report FCN
+ out = in.gloFrequency + 92;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ out = in.svId;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ out = in.svId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ out = in.svId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ out = in.svId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ out = in.svId;
+ break;
+ }
+}
+
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out)
+{
+ switch(in) {
+ case GNSS_EPH_TYPE_EPHEMERIS:
+ out = GnssDebug::SatelliteEphemerisType::EPHEMERIS;
+ break;
+ case GNSS_EPH_TYPE_ALMANAC:
+ out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY;
+ break;
+ case GNSS_EPH_TYPE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE;
+ break;
+ }
+}
+
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out)
+{
+ switch(in) {
+ case GNSS_EPH_SOURCE_DEMODULATED:
+ out = GnssDebug::SatelliteEphemerisSource::DEMODULATED;
+ break;
+ case GNSS_EPH_SOURCE_SUPL_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED;
+ break;
+ case GNSS_EPH_SOURCE_LOCAL:
+ case GNSS_EPH_SOURCE_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisSource::OTHER;
+ break;
+ }
+}
+
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out)
+{
+ switch(in) {
+ case GNSS_EPH_HEALTH_GOOD:
+ out = GnssDebug::SatelliteEphemerisHealth::GOOD;
+ break;
+ case GNSS_EPH_HEALTH_BAD:
+ out = GnssDebug::SatelliteEphemerisHealth::BAD;
+ break;
+ case GNSS_EPH_HEALTH_UNKNOWN:
+ default:
+ out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN;
+ break;
+ }
+}
+
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out)
+{
+ out.flags = GNSS_MEAS_CORR_UNKNOWN_BIT;
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_SAT_IS_LOS_PROBABILITY)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_EXCESS_PATH_LENGTH_UNC)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT;
+ }
+ if (in.singleSatCorrectionFlags & (GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE)) {
+ out.flags |= GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT;
+ }
+ switch (in.constellation) {
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GPS):
+ out.svType = GNSS_SV_TYPE_GPS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::SBAS):
+ out.svType = GNSS_SV_TYPE_SBAS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GLONASS):
+ out.svType = GNSS_SV_TYPE_GLONASS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::QZSS):
+ out.svType = GNSS_SV_TYPE_QZSS;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::BEIDOU):
+ out.svType = GNSS_SV_TYPE_BEIDOU;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::GALILEO):
+ out.svType = GNSS_SV_TYPE_GALILEO;
+ break;
+ case (::android::hardware::gnss::V1_0::GnssConstellationType::UNKNOWN):
+ default:
+ out.svType = GNSS_SV_TYPE_UNKNOWN;
+ break;
+ }
+ out.svId = in.svid;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.probSatIsLos = in.probSatIsLos;
+ out.excessPathLengthMeters = in.excessPathLengthMeters;
+ out.excessPathLengthUncertaintyMeters = in.excessPathLengthUncertaintyMeters;
+
+ out.reflectingPlane.latitudeDegrees = in.reflectingPlane.latitudeDegrees;
+ out.reflectingPlane.longitudeDegrees = in.reflectingPlane.longitudeDegrees;
+ out.reflectingPlane.altitudeMeters = in.reflectingPlane.altitudeMeters;
+ out.reflectingPlane.azimuthDegrees = in.reflectingPlane.azimuthDegrees;
+}
+
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+ GnssMeasurementCorrections& out)
+{
+ memset(&out, 0, sizeof(GnssMeasurementCorrections));
+ out.latitudeDegrees = in.latitudeDegrees;
+ out.longitudeDegrees = in.longitudeDegrees;
+ out.altitudeMeters = in.altitudeMeters;
+ out.horizontalPositionUncertaintyMeters = in.horizontalPositionUncertaintyMeters;
+ out.verticalPositionUncertaintyMeters = in.verticalPositionUncertaintyMeters;
+ out.toaGpsNanosecondsOfWeek = in.toaGpsNanosecondsOfWeek;
+
+ for (int i = 0; i < in.satCorrections.size(); i++) {
+ GnssSingleSatCorrection gnssSingleSatCorrection = {};
+
+ convertSingleSatCorrections(in.satCorrections[i], gnssSingleSatCorrection);
+ out.satCorrections.push_back(gnssSingleSatCorrection);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/LocationUtil.h b/gps/android/2.1/location_api/LocationUtil.h
new file mode 100644
index 0000000..2d95a2d
--- /dev/null
+++ b/gps/android/2.1/location_api/LocationUtil.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOCATION_UTIL_H
+#define LOCATION_UTIL_H
+
+#include <android/hardware/gnss/2.0/types.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <LocationAPI.h>
+#include <GnssDebug.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using MeasurementCorrectionsV1_0 =
+ ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using ::android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+
+void convertGnssLocation(Location& in, V1_0::GnssLocation& out);
+void convertGnssLocation(Location& in, V2_0::GnssLocation& out);
+void convertGnssLocation(const V1_0::GnssLocation& in, Location& out);
+void convertGnssLocation(const V2_0::GnssLocation& in, Location& out);
+void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out);
+void convertGnssConstellationType(GnssSvType& in, V2_0::GnssConstellationType& out);
+void convertGnssSvid(GnssSv& in, int16_t& out);
+void convertGnssSvid(GnssMeasurementsData& in, int16_t& out);
+void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out);
+void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out);
+void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out);
+void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out);
+void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in,
+ GnssMeasurementCorrections& out);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // LOCATION_UTIL_H
diff --git a/gps/android/2.1/location_api/MeasurementAPIClient.cpp b/gps/android/2.1/location_api/MeasurementAPIClient.cpp
new file mode 100644
index 0000000..0028074
--- /dev/null
+++ b/gps/android/2.1/location_api/MeasurementAPIClient.cpp
@@ -0,0 +1,642 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MeasurementAPIClient"
+
+#include <log_util.h>
+#include <loc_cfg.h>
+#include <inttypes.h>
+
+#include "LocationUtil.h"
+#include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+ V2_1::IGnssMeasurementCallback::GnssData& out);
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssClock_2_1(GnssMeasurementsClock& in,
+ V2_1::IGnssMeasurementCallback::GnssClock& out);
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+ char* inOtherCodeTypeName,
+ ::android::hardware::hidl_string& out);
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out);
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
+
+MeasurementAPIClient::MeasurementAPIClient() :
+ mGnssMeasurementCbIface(nullptr),
+ mGnssMeasurementCbIface_1_1(nullptr),
+ mGnssMeasurementCbIface_2_0(nullptr),
+ mGnssMeasurementCbIface_2_1(nullptr),
+ mTracking(false)
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+MeasurementAPIClient::~MeasurementAPIClient()
+{
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+}
+
+void MeasurementAPIClient::clearInterfaces()
+{
+ mGnssMeasurementCbIface = nullptr;
+ mGnssMeasurementCbIface_1_1 = nullptr;
+ mGnssMeasurementCbIface_2_0 = nullptr;
+ mGnssMeasurementCbIface_2_1 = nullptr;
+}
+
+// for GpsInterface
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
+{
+ LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface = callback;
+ mMutex.unlock();
+
+ return startTracking();
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_1_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_2_0 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+
+Return<IGnssMeasurement::GnssMeasurementStatus> MeasurementAPIClient::measurementSetCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) {
+ LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
+ __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);
+
+ mMutex.lock();
+ clearInterfaces();
+ mGnssMeasurementCbIface_2_1 = callback;
+ mMutex.unlock();
+
+ return startTracking(powerMode, timeBetweenMeasurement);
+}
+Return<IGnssMeasurement::GnssMeasurementStatus>
+MeasurementAPIClient::startTracking(
+ GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
+{
+ LocationCallbacks locationCallbacks;
+ memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
+ locationCallbacks.size = sizeof(LocationCallbacks);
+
+ locationCallbacks.trackingCb = nullptr;
+ locationCallbacks.batchingCb = nullptr;
+ locationCallbacks.geofenceBreachCb = nullptr;
+ locationCallbacks.geofenceStatusCb = nullptr;
+ locationCallbacks.gnssLocationInfoCb = nullptr;
+ locationCallbacks.gnssNiCb = nullptr;
+ locationCallbacks.gnssSvCb = nullptr;
+ locationCallbacks.gnssNmeaCb = nullptr;
+
+ locationCallbacks.gnssMeasurementsCb = nullptr;
+ if (mGnssMeasurementCbIface_2_1 != nullptr ||
+ mGnssMeasurementCbIface_2_0 != nullptr ||
+ mGnssMeasurementCbIface_1_1 != nullptr ||
+ mGnssMeasurementCbIface != nullptr) {
+ locationCallbacks.gnssMeasurementsCb =
+ [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
+ onGnssMeasurementsCb(gnssMeasurementsNotification);
+ };
+ }
+
+ locAPISetCallbacks(locationCallbacks);
+
+ TrackingOptions options = {};
+ memset(&options, 0, sizeof(TrackingOptions));
+ options.size = sizeof(TrackingOptions);
+ options.minInterval = 1000;
+ options.mode = GNSS_SUPL_MODE_STANDALONE;
+ if (GNSS_POWER_MODE_INVALID != powerMode) {
+ options.powerMode = powerMode;
+ options.tbm = timeBetweenMeasurement;
+ }
+
+ mTracking = true;
+ LOC_LOGD("%s]: start tracking session", __FUNCTION__);
+ locAPIStartTracking(options);
+ return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+// for GpsMeasurementInterface
+void MeasurementAPIClient::measurementClose() {
+ LOC_LOGD("%s]: ()", __FUNCTION__);
+ mTracking = false;
+ locAPIStopTracking();
+}
+
+// callbacks
+void MeasurementAPIClient::onGnssMeasurementsCb(
+ GnssMeasurementsNotification gnssMeasurementsNotification)
+{
+ LOC_LOGD("%s]: (count: %u active: %d)",
+ __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
+ if (mTracking) {
+ mMutex.lock();
+ sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
+ sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
+ sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr;
+ sp<V2_1::IGnssMeasurementCallback> gnssMeasurementCbIface_2_1 = nullptr;
+ if (mGnssMeasurementCbIface_2_1 != nullptr) {
+ gnssMeasurementCbIface_2_1 = mGnssMeasurementCbIface_2_1;
+ } else if (mGnssMeasurementCbIface_2_0 != nullptr) {
+ gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0;
+ } else if (mGnssMeasurementCbIface_1_1 != nullptr) {
+ gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
+ } else if (mGnssMeasurementCbIface != nullptr) {
+ gnssMeasurementCbIface = mGnssMeasurementCbIface;
+ }
+ mMutex.unlock();
+
+ if (gnssMeasurementCbIface_2_1 != nullptr) {
+ V2_1::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_2_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_2_1->gnssMeasurementCb_2_1(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface_2_0 != nullptr) {
+ V2_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_2_0(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface_1_1 != nullptr) {
+ V1_1::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ } else if (gnssMeasurementCbIface != nullptr) {
+ V1_0::IGnssMeasurementCallback::GnssData gnssData;
+ convertGnssData(gnssMeasurementsNotification, gnssData);
+ auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
+ if (!r.isOk()) {
+ LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
+ __func__, r.description().c_str());
+ }
+ }
+ }
+}
+
+static void convertGnssMeasurement(GnssMeasurementsData& in,
+ V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
+ out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ convertGnssSvid(in, out.svid);
+ convertGnssConstellationType(in.svType, out.constellation);
+ out.timeOffsetNs = in.timeOffsetNs;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ out.receivedSvTimeInNs = in.receivedSvTimeNs;
+ out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
+ out.cN0DbHz = in.carrierToNoiseDbHz;
+ out.pseudorangeRateMps = in.pseudorangeRateMps;
+ out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out.accumulatedDeltaRangeState |=
+ IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ out.accumulatedDeltaRangeM = in.adrMeters;
+ out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
+ out.carrierFrequencyHz = in.carrierFrequencyHz;
+ out.carrierCycles = in.carrierCycles;
+ out.carrierPhase = in.carrierPhase;
+ out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
+ uint8_t indicator =
+ static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
+ if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
+ indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
+ out.multipathIndicator =
+ static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
+ out.snrDb = in.signalToNoiseRatioDb;
+ out.agcLevelDb = in.agcLevelDb;
+}
+
+static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
+ if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
+ out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
+ out.leapSecond = in.leapSecond;
+ out.timeNs = in.timeNs;
+ out.timeUncertaintyNs = in.timeUncertaintyNs;
+ out.fullBiasNs = in.fullBiasNs;
+ out.biasNs = in.biasNs;
+ out.biasUncertaintyNs = in.biasUncertaintyNs;
+ out.driftNsps = in.driftNsps;
+ out.driftUncertaintyNsps = in.driftUncertaintyNsps;
+ out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
+}
+
+static void convertGnssClock_2_1(GnssMeasurementsClock& in,
+ V2_1::IGnssMeasurementCallback::GnssClock& out)
+{
+ memset(&out, 0, sizeof(out));
+ convertGnssClock(in, out.v1_0);
+ convertGnssConstellationType(in.referenceSignalTypeForIsb.svType,
+ out.referenceSignalTypeForIsb.constellation);
+ out.referenceSignalTypeForIsb.carrierFrequencyHz =
+ in.referenceSignalTypeForIsb.carrierFrequencyHz;
+ convertGnssMeasurementsCodeType(in.referenceSignalTypeForIsb.codeType,
+ in.referenceSignalTypeForIsb.otherCodeTypeName,
+ out.referenceSignalTypeForIsb.codeType);
+}
+
+static void convertGnssData(GnssMeasurementsNotification& in,
+ V1_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurementCount = in.count;
+ if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
+ LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
+ __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT);
+ out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
+ }
+ for (size_t i = 0; i < out.measurementCount; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i]);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_1_1(GnssMeasurementsNotification& in,
+ V1_1::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].accumulatedDeltaRangeState);
+ }
+ convertGnssClock(in.clock, out.clock);
+}
+
+static void convertGnssData_2_0(GnssMeasurementsNotification& in,
+ V2_0::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
+ convertGnssConstellationType(in.measurements[i].svType, out.measurements[i].constellation);
+ convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+ in.measurements[i].otherCodeTypeName,
+ out.measurements[i].codeType);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].v1_1.accumulatedDeltaRangeState);
+ convertGnssMeasurementsState(in.measurements[i].stateMask, out.measurements[i].state);
+ }
+ convertGnssClock(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
+ char* inOtherCodeTypeName, ::android::hardware::hidl_string& out)
+{
+ memset(&out, 0, sizeof(out));
+ switch(inCodeType) {
+ case GNSS_MEASUREMENTS_CODE_TYPE_A:
+ out = "A";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_B:
+ out = "B";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_C:
+ out = "C";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_I:
+ out = "I";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_L:
+ out = "L";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_M:
+ out = "M";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_P:
+ out = "P";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Q:
+ out = "Q";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_S:
+ out = "S";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_W:
+ out = "W";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_X:
+ out = "X";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Y:
+ out = "Y";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_Z:
+ out = "Z";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_N:
+ out = "N";
+ break;
+ case GNSS_MEASUREMENTS_CODE_TYPE_OTHER:
+ default:
+ out = inOtherCodeTypeName;
+ break;
+ }
+}
+
+static void convertGnssMeasurementsAccumulatedDeltaRangeState(GnssMeasurementsAdrStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
+ out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
+ if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
+ out |= IGnssMeasurementCallback::
+ GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
+}
+
+static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
+ ::android::hardware::hidl_bitfield
+ <V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out)
+{
+ memset(&out, 0, sizeof(out));
+ if (in & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
+ if (in & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
+ if (in & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
+ if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
+ if (in & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
+ if (in & GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+ if (in & GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+ if (in & GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
+ out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
+}
+
+static void convertGnssData_2_1(GnssMeasurementsNotification& in,
+ V2_1::IGnssMeasurementCallback::GnssData& out)
+{
+ memset(&out, 0, sizeof(out));
+ out.measurements.resize(in.count);
+ for (size_t i = 0; i < in.count; i++) {
+ out.measurements[i].flags = 0;
+ convertGnssMeasurement(in.measurements[i], out.measurements[i].v2_0.v1_1.v1_0);
+ convertGnssConstellationType(in.measurements[i].svType,
+ out.measurements[i].v2_0.constellation);
+ convertGnssMeasurementsCodeType(in.measurements[i].codeType,
+ in.measurements[i].otherCodeTypeName,
+ out.measurements[i].v2_0.codeType);
+ convertGnssMeasurementsAccumulatedDeltaRangeState(in.measurements[i].adrStateMask,
+ out.measurements[i].v2_0.v1_1.accumulatedDeltaRangeState);
+ convertGnssMeasurementsState(in.measurements[i].stateMask,
+ out.measurements[i].v2_0.state);
+ out.measurements[i].basebandCN0DbHz = in.measurements[i].basebandCarrierToNoiseDbHz;
+
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) {
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT) {
+ out.measurements[i].fullInterSignalBiasNs = in.measurements[i].fullInterSignalBiasNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_FULL_ISB;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT) {
+ out.measurements[i].fullInterSignalBiasUncertaintyNs =
+ in.measurements[i].fullInterSignalBiasUncertaintyNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT) {
+ out.measurements[i].satelliteInterSignalBiasNs =
+ in.measurements[i].satelliteInterSignalBiasNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SATELLITE_ISB;
+ }
+ if (in.measurements[i].flags & GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT) {
+ out.measurements[i].satelliteInterSignalBiasUncertaintyNs =
+ in.measurements[i].satelliteInterSignalBiasUncertaintyNs;
+ out.measurements[i].flags |=
+ V2_1::IGnssMeasurementCallback::
+ GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY;
+ }
+ }
+ convertGnssClock_2_1(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+ if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+ LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
+ " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
+ elapsedRealtime.timestampNs,
+ elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gps/android/2.1/location_api/MeasurementAPIClient.h b/gps/android/2.1/location_api/MeasurementAPIClient.h
new file mode 100644
index 0000000..3e8805b
--- /dev/null
+++ b/gps/android/2.1/location_api/MeasurementAPIClient.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MEASUREMENT_API_CLINET_H
+#define MEASUREMENT_API_CLINET_H
+
+#include <mutex>
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
+#include <android/hardware/gnss/2.1/IGnssMeasurementCallback.h>
+#include <LocationAPIClientBase.h>
+#include <hidl/Status.h>
+#include <gps_extended_c.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+
+class MeasurementAPIClient : public LocationAPIClientBase
+{
+public:
+ MeasurementAPIClient();
+ MeasurementAPIClient(const MeasurementAPIClient&) = delete;
+ MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;
+
+ // for GpsMeasurementInterface
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
+ const sp<V1_0::IGnssMeasurementCallback>& callback);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
+ const sp<V1_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0(
+ const sp<V2_0::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_1(
+ const sp<V2_1::IGnssMeasurementCallback>& callback,
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+ void measurementClose();
+ Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
+ GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
+ uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
+
+ // callbacks we are interested in
+ void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;
+
+private:
+ virtual ~MeasurementAPIClient();
+
+ std::mutex mMutex;
+ sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
+ sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
+ sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
+ sp<V2_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_1;
+ bool mTracking;
+ void clearInterfaces();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+#endif // MEASUREMENT_API_CLINET_H
diff --git a/gps/android/2.1/service.cpp b/gps/android/2.1/service.cpp
new file mode 100755
index 0000000..c5f040b
--- /dev/null
+++ b/gps/android/2.1/service.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ */
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2_0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2_0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@2.1-service-qti"
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <hidl/LegacySupport.h>
+#include "loc_cfg.h"
+#include "loc_misc_utils.h"
+
+extern "C" {
+#include "vndfwk-detect.h"
+}
+
+#ifdef ARCH_ARM_32
+#define DEFAULT_HW_BINDER_MEM_SIZE 65536
+#endif
+
+using android::hardware::gnss::V2_1::IGnss;
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::joinRpcThreadpool;
+
+using android::status_t;
+using android::OK;
+
+typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);
+
+int main() {
+
+ ALOGI("%s", __FUNCTION__);
+
+ int vendorInfo = getVendorEnhancedInfo();
+ bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
+ setVendorEnhanced(vendorEnhanced);
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
+#endif
+ configureRpcThreadpool(1, true);
+ status_t status;
+
+ status = registerPassthroughServiceImplementation<IGnss>();
+ if (status == OK) {
+ #ifdef LOC_HIDL_VERSION
+ #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"
+
+ void* libHandle = NULL;
+ vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
+ dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
+ if (NULL != vendorEnhancedMainMethod) {
+ (*vendorEnhancedMainMethod)(0, NULL);
+ }
+ #else
+ ALOGI("LOC_HIDL_VERSION not defined.");
+ #endif
+ joinRpcThreadpool();
+ } else {
+ ALOGE("Error while registering IGnss 2.1 service: %d", status);
+ }
+
+ return 0;
+}
diff --git a/gps/android/Android.mk b/gps/android/Android.mk
new file mode 100644
index 0000000..aa2f4b5
--- /dev/null
+++ b/gps/android/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-subdir-makefiles)
diff --git a/gps/android/utils/Android.bp b/gps/android/utils/Android.bp
new file mode 100644
index 0000000..c3dc17a
--- /dev/null
+++ b/gps/android/utils/Android.bp
@@ -0,0 +1,37 @@
+cc_library_static {
+
+ name: "liblocbatterylistener",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ cflags: GNSS_CFLAGS + ["-DBATTERY_LISTENER_ENABLED"],
+ local_include_dirs: ["."],
+
+ srcs: ["battery_listener.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libcutils",
+ "libutils",
+ "android.hardware.health@1.0",
+ "android.hardware.health@2.0",
+ "android.hardware.health@2.1",
+ "android.hardware.power@1.2",
+ "libbase",
+ ],
+
+ static_libs: ["libhealthhalutils"],
+
+ header_libs: [
+ "libgps.utils_headers",
+ "libloc_pla_headers",
+ ],
+}
+
+cc_library_headers {
+
+ name: "liblocbatterylistener_headers",
+ export_include_dirs: ["."],
+}
diff --git a/gps/android/utils/battery_listener.cpp b/gps/android/utils/battery_listener.cpp
new file mode 100644
index 0000000..9cbfabd
--- /dev/null
+++ b/gps/android/utils/battery_listener.cpp
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "battery_listener.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "LocSvc_BatteryListener"
+#define LOG_NDEBUG 0
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hardware/health/2.1/IHealth.h>
+#include <android/hardware/health/2.1/IHealthInfoCallback.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <hidl/HidlTransportSupport.h>
+#include <thread>
+#include <log_util.h>
+
+using android::hardware::interfacesEqual;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V2_1::IHealthInfoCallback;
+using android::hardware::health::V2_1::IHealth;
+using android::hardware::health::V2_0::Result;
+using android::hidl::manager::V1_0::IServiceManager;
+using namespace std::literals::chrono_literals;
+
+static bool sIsBatteryListened = false;
+namespace android {
+
+#define GET_HEALTH_SVC_RETRY_CNT 5
+#define GET_HEALTH_SVC_WAIT_TIME_MS 500
+
+struct BatteryListenerImpl : public hardware::health::V2_1::IHealthInfoCallback,
+ public hardware::hidl_death_recipient {
+ typedef std::function<void(bool)> cb_fn_t;
+ BatteryListenerImpl(cb_fn_t cb);
+ virtual ~BatteryListenerImpl ();
+ virtual hardware::Return<void> healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info);
+ virtual hardware::Return<void> healthInfoChanged_2_1(
+ const hardware::health::V2_1::HealthInfo& info);
+ virtual void serviceDied(uint64_t cookie,
+ const wp<hidl::base::V1_0::IBase>& who);
+ bool isCharging() {
+ std::lock_guard<std::mutex> _l(mLock);
+ return statusToBool(mStatus);
+ }
+ private:
+ sp<hardware::health::V2_1::IHealth> mHealth;
+ status_t init();
+ BatteryStatus mStatus;
+ cb_fn_t mCb;
+ std::mutex mLock;
+ std::condition_variable mCond;
+ std::unique_ptr<std::thread> mThread;
+ bool mDone;
+ bool statusToBool(const BatteryStatus &s) const {
+ return (s == BatteryStatus::CHARGING) ||
+ (s == BatteryStatus::FULL);
+ }
+};
+
+status_t BatteryListenerImpl::init()
+{
+ int tries = 0;
+
+ if (mHealth != NULL)
+ return INVALID_OPERATION;
+
+ do {
+ mHealth = IHealth::getService();
+ if (mHealth != NULL)
+ break;
+ usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000);
+ tries++;
+ } while(tries < GET_HEALTH_SVC_RETRY_CNT);
+
+ if (mHealth == NULL) {
+ LOC_LOGe("no health service found, retries %d", tries);
+ return NO_INIT;
+ } else {
+ LOC_LOGi("Get health service in %d tries", tries);
+ }
+ mStatus = BatteryStatus::UNKNOWN;
+ auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) {
+ if (r != Result::SUCCESS) {
+ LOC_LOGe("batterylistener: cannot get battery status");
+ return;
+ }
+ mStatus = status;
+ });
+ if (!ret.isOk()) {
+ LOC_LOGe("batterylistener: get charge status transaction error");
+ }
+ if (mStatus == BatteryStatus::UNKNOWN) {
+ LOC_LOGw("batterylistener: init: invalid battery status");
+ }
+ mDone = false;
+ mThread = std::make_unique<std::thread>([this]() {
+ std::unique_lock<std::mutex> l(mLock);
+ BatteryStatus local_status = mStatus;
+ while (!mDone) {
+ if (local_status == mStatus) {
+ mCond.wait(l);
+ continue;
+ }
+ local_status = mStatus;
+ switch (local_status) {
+ // NOT_CHARGING is a special event that indicates, a battery is connected,
+ // but not charging. This is seen for approx a second
+ // after charger is plugged in. A charging event is eventually received.
+ // We must try to avoid an unnecessary cb to HAL
+ // only to call it again shortly.
+ // An option to deal with this transient event would be to ignore this.
+ // Or process this event with a slight delay (i.e cancel this event
+ // if a different event comes in within a timeout
+ case BatteryStatus::NOT_CHARGING : {
+ auto mStatusnot_ncharging =
+ [this, local_status]() { return mStatus != local_status; };
+ mCond.wait_for(l, 3s, mStatusnot_ncharging);
+ if (mStatusnot_ncharging()) // i.e event changed
+ break;
+ [[clang::fallthrough]]; //explicit fall-through between switch labels
+ }
+ default:
+ bool c = statusToBool(local_status);
+ LOC_LOGi("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING");
+ l.unlock();
+ mCb(c);
+ l.lock();
+ break;
+ }
+ }
+ });
+ auto reg = mHealth->registerCallback(this);
+ if (!reg.isOk()) {
+ LOC_LOGe("Transaction error in registeringCb to HealthHAL death: %s",
+ reg.description().c_str());
+ }
+
+ auto linked = mHealth->linkToDeath(this, 0 /* cookie */);
+ if (!linked.isOk() || linked == false) {
+ LOC_LOGe("Transaction error in linking to HealthHAL death: %s",
+ linked.description().c_str());
+ }
+ return NO_ERROR;
+}
+
+BatteryListenerImpl::BatteryListenerImpl(cb_fn_t cb) :
+ mCb(cb)
+{
+ init();
+}
+
+BatteryListenerImpl::~BatteryListenerImpl()
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth != NULL)
+ mHealth->unregisterCallback(this);
+ auto r = mHealth->unlinkToDeath(this);
+ if (!r.isOk() || r == false) {
+ LOC_LOGe("Transaction error in unregister to HealthHAL death: %s",
+ r.description().c_str());
+ }
+ }
+ mDone = true;
+ mThread->join();
+}
+
+void BatteryListenerImpl::serviceDied(uint64_t cookie __unused,
+ const wp<hidl::base::V1_0::IBase>& who)
+{
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) {
+ LOC_LOGe("health not initialized or unknown interface died");
+ return;
+ }
+ LOC_LOGi("health service died, reinit");
+ mDone = true;
+ }
+ mHealth = NULL;
+ mCond.notify_one();
+ mThread->join();
+ std::lock_guard<std::mutex> _l(mLock);
+ init();
+}
+
+// this callback seems to be a SYNC callback and so
+// waits for return before next event is issued.
+// therefore we need not have a queue to process
+// NOT_CHARGING and CHARGING concurrencies.
+// Replace single var by a list if this assumption is broken
+Return<void> BatteryListenerImpl::healthInfoChanged(
+ const hardware::health::V2_0::HealthInfo& info) {
+ LOC_LOGv("healthInfoChanged: %d", info.legacy.batteryStatus);
+ std::unique_lock<std::mutex> l(mLock);
+ if (info.legacy.batteryStatus != mStatus) {
+ mStatus = info.legacy.batteryStatus;
+ mCond.notify_one();
+ }
+ return Void();
+}
+
+Return<void> BatteryListenerImpl::healthInfoChanged_2_1(
+ const hardware::health::V2_1::HealthInfo& info) {
+ LOC_LOGv("healthInfoChanged_2_1: %d", info.legacy.legacy.batteryStatus);
+ healthInfoChanged(info.legacy);
+ return Void();
+}
+
+static sp<BatteryListenerImpl> batteryListener;
+
+bool batteryPropertiesListenerIsCharging() {
+ return batteryListener->isCharging();
+}
+
+status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb) {
+ batteryListener = new BatteryListenerImpl(cb);
+ bool isCharging = batteryPropertiesListenerIsCharging();
+ LOC_LOGv("charging status: %s charging", isCharging ? "" : "not");;
+ if (isCharging) {
+ cb(isCharging);
+ }
+ return NO_ERROR;
+}
+
+status_t batteryPropertiesListenerDeinit() {
+ batteryListener.clear();
+ return OK;
+}
+
+} // namespace android
+
+void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) {
+ LOC_LOGv("loc_extn_battery_properties_listener_init entry");
+ if (!sIsBatteryListened) {
+ std::thread t1(android::batteryPropertiesListenerInit,
+ [=](bool charging) { fn(charging); });
+ t1.detach();
+ sIsBatteryListened = true;
+ }
+}
+
+void loc_extn_battery_properties_listener_deinit() {
+ android::batteryPropertiesListenerDeinit();
+}
+
+bool loc_extn_battery_properties_is_charging() {
+ return android::batteryPropertiesListenerIsCharging();
+}
diff --git a/gps/android/utils/battery_listener.h b/gps/android/utils/battery_listener.h
new file mode 100644
index 0000000..bb6b715
--- /dev/null
+++ b/gps/android/utils/battery_listener.h
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+typedef void (* battery_status_change_fn_t)(bool);
+void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn);
+void loc_extn_battery_properties_listener_deinit();
+bool loc_extn_battery_properties_is_charging();
diff --git a/gps/batching/Android.bp b/gps/batching/Android.bp
new file mode 100644
index 0000000..9182a0a
--- /dev/null
+++ b/gps/batching/Android.bp
@@ -0,0 +1,31 @@
+
+cc_library_shared {
+
+ name: "libbatching",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ shared_libs: [
+ "libutils",
+ "libcutils",
+ "liblog",
+ "libloc_core",
+ "libgps.utils",
+ "libdl",
+ ],
+
+ srcs: [
+ "location_batching.cpp",
+ "BatchingAdapter.cpp",
+ ],
+
+ header_libs: [
+ "libgps.utils_headers",
+ "libloc_core_headers",
+ "libloc_pla_headers",
+ "liblocation_api_headers",
+ ],
+
+ cflags: GNSS_CFLAGS,
+}
diff --git a/gps/batching/BatchingAdapter.cpp b/gps/batching/BatchingAdapter.cpp
new file mode 100644
index 0000000..d9f7945
--- /dev/null
+++ b/gps/batching/BatchingAdapter.cpp
@@ -0,0 +1,1045 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_BatchingAdapter"
+
+#include <loc_pla.h>
+#include <log_util.h>
+#include <LocContext.h>
+#include <BatchingAdapter.h>
+
+using namespace loc_core;
+
+BatchingAdapter::BatchingAdapter() :
+ LocAdapterBase(0, LocContext::getLocContext(LocContext::mLocationHalName)),
+ mOngoingTripDistance(0),
+ mOngoingTripTBFInterval(0),
+ mTripWithOngoingTBFDropped(false),
+ mTripWithOngoingTripDistanceDropped(false),
+ mBatchingTimeout(0),
+ mBatchingAccuracy(1),
+ mBatchSize(0),
+ mTripBatchSize(0)
+{
+ LOC_LOGD("%s]: Constructor", __func__);
+ readConfigCommand();
+ setConfigCommand();
+}
+
+void
+BatchingAdapter::readConfigCommand()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgReadConfig : public LocMsg {
+ BatchingAdapter& mAdapter;
+ inline MsgReadConfig(BatchingAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ inline virtual void proc() const {
+ uint32_t batchingTimeout = 0;
+ uint32_t batchingAccuracy = 0;
+ uint32_t batchSize = 0;
+ uint32_t tripBatchSize = 0;
+ static const loc_param_s_type flp_conf_param_table[] =
+ {
+ {"BATCH_SIZE", &batchSize, NULL, 'n'},
+ {"OUTDOOR_TRIP_BATCH_SIZE", &tripBatchSize, NULL, 'n'},
+ {"BATCH_SESSION_TIMEOUT", &batchingTimeout, NULL, 'n'},
+ {"ACCURACY", &batchingAccuracy, NULL, 'n'},
+ };
+ UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
+
+ LOC_LOGD("%s]: batchSize %u tripBatchSize %u batchingAccuracy %u batchingTimeout %u ",
+ __func__, batchSize, tripBatchSize, batchingAccuracy, batchingTimeout);
+
+ mAdapter.setBatchSize(batchSize);
+ mAdapter.setTripBatchSize(tripBatchSize);
+ mAdapter.setBatchingTimeout(batchingTimeout);
+ mAdapter.setBatchingAccuracy(batchingAccuracy);
+ }
+ };
+
+ sendMsg(new MsgReadConfig(*this));
+
+}
+
+void
+BatchingAdapter::setConfigCommand()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgSetConfig : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ inline MsgSetConfig(BatchingAdapter& adapter,
+ LocApiBase& api) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api) {}
+ inline virtual void proc() const {
+ mApi.setBatchSize(mAdapter.getBatchSize());
+ mApi.setTripBatchSize(mAdapter.getTripBatchSize());
+ }
+ };
+
+ sendMsg(new MsgSetConfig(*this, *mLocApi));
+}
+
+void
+BatchingAdapter::stopClientSessions(LocationAPI* client)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+ typedef struct pairKeyBatchMode {
+ LocationAPI* client;
+ uint32_t id;
+ BatchingMode batchingMode;
+ inline pairKeyBatchMode(LocationAPI* _client, uint32_t _id, BatchingMode _bMode) :
+ client(_client), id(_id), batchingMode(_bMode) {}
+ } pairKeyBatchMode;
+ std::vector<pairKeyBatchMode> vBatchingClient;
+ for (auto it : mBatchingSessions) {
+ if (client == it.first.client) {
+ vBatchingClient.emplace_back(it.first.client, it.first.id, it.second.batchingMode);
+ }
+ }
+ for (auto keyBatchingMode : vBatchingClient) {
+ if (keyBatchingMode.batchingMode != BATCHING_MODE_TRIP) {
+ stopBatching(keyBatchingMode.client, keyBatchingMode.id);
+ } else {
+ stopTripBatchingMultiplex(keyBatchingMode.client, keyBatchingMode.id);
+ }
+ }
+}
+
+void
+BatchingAdapter::updateClientsEventMask()
+{
+ LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ // we don't register LOC_API_ADAPTER_BIT_BATCH_FULL until we
+ // start batching with ROUTINE or TRIP option
+ if (it->second.batchingCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_BATCH_STATUS;
+ }
+ }
+ if (autoReportBatchingSessionsCount() > 0) {
+ mask |= LOC_API_ADAPTER_BIT_BATCH_FULL;
+ }
+ updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
+}
+
+void
+BatchingAdapter::handleEngineUpEvent()
+{
+ struct MsgSSREvent : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ inline MsgSSREvent(BatchingAdapter& adapter,
+ LocApiBase& api) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api) {}
+ virtual void proc() const {
+ mAdapter.setEngineCapabilitiesKnown(true);
+ mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+ mApi.setBatchSize(mAdapter.getBatchSize());
+ mApi.setTripBatchSize(mAdapter.getTripBatchSize());
+ mAdapter.restartSessions();
+ for (auto msg: mAdapter.mPendingMsgs) {
+ mAdapter.sendMsg(msg);
+ }
+ mAdapter.mPendingMsgs.clear();
+ }
+ };
+
+ sendMsg(new MsgSSREvent(*this, *mLocApi));
+}
+
+void
+BatchingAdapter::restartSessions()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ if (autoReportBatchingSessionsCount() > 0) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_ENABLED);
+ }
+ for (auto it = mBatchingSessions.begin();
+ it != mBatchingSessions.end(); ++it) {
+ if (it->second.batchingMode != BATCHING_MODE_TRIP) {
+ mLocApi->startBatching(it->first.id, it->second,
+ getBatchingAccuracy(), getBatchingTimeout(),
+ new LocApiResponse(*getContext(),
+ [] (LocationError /*err*/) {}));
+ }
+ }
+
+ if (mTripSessions.size() > 0) {
+ // restart outdoor trip batching session if any.
+ mOngoingTripDistance = 0;
+ mOngoingTripTBFInterval = 0;
+
+ // record the min trip distance and min tbf interval of all ongoing sessions
+ for (auto tripSession : mTripSessions) {
+
+ TripSessionStatus &tripSessStatus = tripSession.second;
+
+ if ((0 == mOngoingTripDistance) ||
+ (mOngoingTripDistance >
+ (tripSessStatus.tripDistance - tripSessStatus.accumulatedDistanceThisTrip))) {
+ mOngoingTripDistance = tripSessStatus.tripDistance -
+ tripSessStatus.accumulatedDistanceThisTrip;
+ }
+
+ if ((0 == mOngoingTripTBFInterval) ||
+ (mOngoingTripTBFInterval > tripSessStatus.tripTBFInterval)) {
+ mOngoingTripTBFInterval = tripSessStatus.tripTBFInterval;
+ }
+
+ // reset the accumulatedDistanceOngoingBatch for each session
+ tripSessStatus.accumulatedDistanceOngoingBatch = 0;
+
+ }
+
+ mLocApi->startOutdoorTripBatching(mOngoingTripDistance, mOngoingTripTBFInterval,
+ getBatchingTimeout(), new LocApiResponse(*getContext(), [this] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ mOngoingTripDistance = 0;
+ mOngoingTripTBFInterval = 0;
+ }
+ printTripReport();
+ }));
+ }
+}
+
+bool
+BatchingAdapter::hasBatchingCallback(LocationAPI* client)
+{
+ auto it = mClientData.find(client);
+ return (it != mClientData.end() && it->second.batchingCb);
+}
+
+bool
+BatchingAdapter::isBatchingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ return (mBatchingSessions.find(key) != mBatchingSessions.end());
+}
+
+bool
+BatchingAdapter::isTripSession(uint32_t sessionId) {
+ return (mTripSessions.find(sessionId) != mTripSessions.end());
+}
+
+void
+BatchingAdapter::saveBatchingSession(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions)
+{
+ LocationSessionKey key(client, sessionId);
+ mBatchingSessions[key] = batchingOptions;
+}
+
+void
+BatchingAdapter::eraseBatchingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ auto it = mBatchingSessions.find(key);
+ if (it != mBatchingSessions.end()) {
+ mBatchingSessions.erase(it);
+ }
+}
+
+void
+BatchingAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
+{
+ LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
+
+ auto it = mClientData.find(client);
+ if (it != mClientData.end() &&
+ it->second.responseCb != nullptr) {
+ it->second.responseCb(err, sessionId);
+ } else {
+ LOC_LOGE("%s]: client %p id %u not found in data", __func__, client, sessionId);
+ }
+}
+
+uint32_t
+BatchingAdapter::autoReportBatchingSessionsCount()
+{
+ uint32_t count = 0;
+ for (auto batchingSession: mBatchingSessions) {
+ if (batchingSession.second.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) {
+ count++;
+ }
+ }
+ count += mTripSessions.size();
+ return count;
+}
+
+uint32_t
+BatchingAdapter::startBatchingCommand(
+ LocationAPI* client, BatchingOptions& batchOptions)
+{
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u Batching Mode %d",
+ __func__, client, sessionId, batchOptions.minInterval, batchOptions.minDistance,
+ batchOptions.mode,batchOptions.batchingMode);
+
+ struct MsgStartBatching : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ BatchingOptions mBatchingOptions;
+ inline MsgStartBatching(BatchingAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId,
+ BatchingOptions batchOptions) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId),
+ mBatchingOptions(batchOptions) {}
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgStartBatching(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+
+ if (!mAdapter.hasBatchingCallback(mClient)) {
+ err = LOCATION_ERROR_CALLBACK_MISSING;
+ } else if (0 == mBatchingOptions.size) {
+ err = LOCATION_ERROR_INVALID_PARAMETER;
+ } else if (!ContextBase::isMessageSupported(
+ LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
+ err = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (mBatchingOptions.batchingMode == BATCHING_MODE_ROUTINE ||
+ mBatchingOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) {
+ mAdapter.startBatching(mClient, mSessionId, mBatchingOptions);
+ } else if (mBatchingOptions.batchingMode == BATCHING_MODE_TRIP) {
+ mAdapter.startTripBatchingMultiplex(mClient, mSessionId, mBatchingOptions);
+ } else {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_INVALID_PARAMETER, mSessionId);
+ }
+ }
+ }
+ };
+
+ sendMsg(new MsgStartBatching(*this, *mLocApi, client, sessionId, batchOptions));
+
+ return sessionId;
+}
+
+void
+BatchingAdapter::startBatching(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions)
+{
+ if (batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT &&
+ 0 == autoReportBatchingSessionsCount()) {
+ // if there is currenty no batching sessions interested in batch full event, then this
+ // new session will need to register for batch full event
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_ENABLED);
+ }
+
+ // Assume start will be OK, remove session if not
+ saveBatchingSession(client, sessionId, batchingOptions);
+ mLocApi->startBatching(sessionId, batchingOptions, getBatchingAccuracy(), getBatchingTimeout(),
+ new LocApiResponse(*getContext(),
+ [this, client, sessionId, batchingOptions] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ eraseBatchingSession(client, sessionId);
+ }
+
+ if (LOCATION_ERROR_SUCCESS != err &&
+ batchingOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT &&
+ 0 == autoReportBatchingSessionsCount()) {
+ // if we fail to start batching and we have already registered batch full event
+ // we need to undo that since no sessions are now interested in batch full event
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+
+ reportResponse(client, err, sessionId);
+ }));
+}
+
+void
+BatchingAdapter::updateBatchingOptionsCommand(LocationAPI* client, uint32_t id,
+ BatchingOptions& batchOptions)
+{
+ LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u batchMode %u",
+ __func__, client, id, batchOptions.minInterval,
+ batchOptions.minDistance, batchOptions.mode,
+ batchOptions.batchingMode);
+
+ struct MsgUpdateBatching : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ BatchingOptions mBatchOptions;
+ inline MsgUpdateBatching(BatchingAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId,
+ BatchingOptions batchOptions) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId),
+ mBatchOptions(batchOptions) {}
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgUpdateBatching(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ if (!mAdapter.isBatchingSession(mClient, mSessionId)) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ } else if ((0 == mBatchOptions.size) ||
+ (mBatchOptions.batchingMode > BATCHING_MODE_NO_AUTO_REPORT)) {
+ err = LOCATION_ERROR_INVALID_PARAMETER;
+ }
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (!mAdapter.isTripSession(mSessionId)) {
+ mAdapter.stopBatching(mClient, mSessionId, true, mBatchOptions);
+ } else {
+ mAdapter.stopTripBatchingMultiplex(mClient, mSessionId, true, mBatchOptions);
+ }
+ }
+ }
+ };
+
+ sendMsg(new MsgUpdateBatching(*this, *mLocApi, client, id, batchOptions));
+}
+
+void
+BatchingAdapter::stopBatchingCommand(LocationAPI* client, uint32_t id)
+{
+ LOC_LOGD("%s]: client %p id %u", __func__, client, id);
+
+ struct MsgStopBatching : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ inline MsgStopBatching(BatchingAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId) {}
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgStopBatching(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ if (!mAdapter.isBatchingSession(mClient, mSessionId)) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ }
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (mAdapter.isTripSession(mSessionId)) {
+ mAdapter.stopTripBatchingMultiplex(mClient, mSessionId);
+ } else {
+ mAdapter.stopBatching(mClient, mSessionId);
+ }
+ }
+ }
+ };
+
+ sendMsg(new MsgStopBatching(*this, *mLocApi, client, id));
+}
+
+void
+BatchingAdapter::stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded,
+ const BatchingOptions& batchOptions)
+{
+ LocationSessionKey key(client, sessionId);
+ auto it = mBatchingSessions.find(key);
+ if (it != mBatchingSessions.end()) {
+ auto flpOptions = it->second;
+ // Assume stop will be OK, restore session if not
+ eraseBatchingSession(client, sessionId);
+ mLocApi->stopBatching(sessionId,
+ new LocApiResponse(*getContext(),
+ [this, client, sessionId, flpOptions, restartNeeded, batchOptions]
+ (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ saveBatchingSession(client, sessionId, batchOptions);
+ } else {
+ // if stopBatching is success, unregister for batch full event if this was the last
+ // batching session that is interested in batch full event
+ if (0 == autoReportBatchingSessionsCount() &&
+ flpOptions.batchingMode != BATCHING_MODE_NO_AUTO_REPORT) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+
+ if (restartNeeded) {
+ if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE ||
+ batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) {
+ startBatching(client, sessionId, batchOptions);
+ } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) {
+ startTripBatchingMultiplex(client, sessionId, batchOptions);
+ }
+ }
+ }
+ reportResponse(client, err, sessionId);
+ }));
+ }
+}
+
+void
+BatchingAdapter::getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count)
+{
+ LOC_LOGD("%s]: client %p id %u count %zu", __func__, client, id, count);
+
+ struct MsgGetBatchedLocations : public LocMsg {
+ BatchingAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ size_t mCount;
+ inline MsgGetBatchedLocations(BatchingAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId,
+ size_t count) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId),
+ mCount(count) {}
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgGetBatchedLocations(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ if (!mAdapter.hasBatchingCallback(mClient)) {
+ err = LOCATION_ERROR_CALLBACK_MISSING;
+ } else if (!mAdapter.isBatchingSession(mClient, mSessionId)) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ }
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (mAdapter.isTripSession(mSessionId)) {
+ mApi.getBatchedTripLocations(mCount, 0,
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId,
+ mClient = mClient] (LocationError err) {
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }));
+ } else {
+ mApi.getBatchedLocations(mCount, new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId,
+ mClient = mClient] (LocationError err) {
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }));
+ }
+ } else {
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }
+ }
+ };
+
+ sendMsg(new MsgGetBatchedLocations(*this, *mLocApi, client, id, count));
+}
+
+void
+BatchingAdapter::reportLocationsEvent(const Location* locations, size_t count,
+ BatchingMode batchingMode)
+{
+ LOC_LOGD("%s]: count %zu batchMode %d", __func__, count, batchingMode);
+
+ struct MsgReportLocations : public LocMsg {
+ BatchingAdapter& mAdapter;
+ Location* mLocations;
+ size_t mCount;
+ BatchingMode mBatchingMode;
+ inline MsgReportLocations(BatchingAdapter& adapter,
+ const Location* locations,
+ size_t count,
+ BatchingMode batchingMode) :
+ LocMsg(),
+ mAdapter(adapter),
+ mLocations(new Location[count]),
+ mCount(count),
+ mBatchingMode(batchingMode)
+ {
+ if (nullptr == mLocations) {
+ LOC_LOGE("%s]: new failed to allocate mLocations", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ mLocations[i] = locations[i];
+ }
+ }
+ inline virtual ~MsgReportLocations() {
+ if (nullptr != mLocations)
+ delete[] mLocations;
+ }
+ inline virtual void proc() const {
+ mAdapter.reportLocations(mLocations, mCount, mBatchingMode);
+ }
+ };
+
+ sendMsg(new MsgReportLocations(*this, locations, count, batchingMode));
+}
+
+void
+BatchingAdapter::reportLocations(Location* locations, size_t count, BatchingMode batchingMode)
+{
+ BatchingOptions batchOptions = {sizeof(BatchingOptions), batchingMode};
+
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.batchingCb) {
+ it->second.batchingCb(count, locations, batchOptions);
+ }
+ }
+}
+
+void
+BatchingAdapter::reportCompletedTripsEvent(uint32_t accumulated_distance)
+{
+ struct MsgReportCompletedTrips : public LocMsg {
+ BatchingAdapter& mAdapter;
+ uint32_t mAccumulatedDistance;
+ inline MsgReportCompletedTrips(BatchingAdapter& adapter,
+ uint32_t accumulated_distance) :
+ LocMsg(),
+ mAdapter(adapter),
+ mAccumulatedDistance(accumulated_distance)
+ {
+ }
+ inline virtual ~MsgReportCompletedTrips() {
+ }
+ inline virtual void proc() const {
+
+ // Check if any trips are completed
+ std::list<uint32_t> completedTripsList;
+ completedTripsList.clear();
+
+ for(auto itt = mAdapter.mTripSessions.begin(); itt != mAdapter.mTripSessions.end();)
+ {
+ TripSessionStatus &tripSession = itt->second;
+
+ tripSession.accumulatedDistanceThisTrip =
+ tripSession.accumulatedDistanceOnTripRestart
+ + (mAccumulatedDistance - tripSession.accumulatedDistanceOngoingBatch);
+ if (tripSession.tripDistance <= tripSession.accumulatedDistanceThisTrip) {
+ // trip is completed
+ completedTripsList.push_back(itt->first);
+ itt = mAdapter.mTripSessions.erase(itt);
+
+ if (tripSession.tripTBFInterval == mAdapter.mOngoingTripTBFInterval) {
+ // trip with ongoing TBF interval is completed
+ mAdapter.mTripWithOngoingTBFDropped = true;
+ }
+
+ if (tripSession.tripDistance == mAdapter.mOngoingTripDistance) {
+ // trip with ongoing trip distance is completed
+ mAdapter.mTripWithOngoingTripDistanceDropped = true;
+ }
+ } else {
+ itt++;
+ }
+ }
+
+ if (completedTripsList.size() > 0) {
+ mAdapter.reportBatchStatusChange(BATCHING_STATUS_TRIP_COMPLETED,
+ completedTripsList);
+ mAdapter.restartTripBatching(false, mAccumulatedDistance, 0);
+ } else {
+ mAdapter.printTripReport();
+ }
+ }
+ };
+
+ LOC_LOGD("%s]: Accumulated Distance so far: %u",
+ __func__, accumulated_distance);
+
+ sendMsg(new MsgReportCompletedTrips(*this, accumulated_distance));
+}
+
+void
+BatchingAdapter::reportBatchStatusChange(BatchingStatus batchStatus,
+ std::list<uint32_t> & completedTripsList)
+{
+ BatchingStatusInfo batchStatusInfo =
+ {sizeof(BatchingStatusInfo), batchStatus};
+
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.batchingStatusCb) {
+ it->second.batchingStatusCb(batchStatusInfo, completedTripsList);
+ }
+ }
+}
+
+void
+BatchingAdapter::reportBatchStatusChangeEvent(BatchingStatus batchStatus)
+{
+ struct MsgReportBatchStatus : public LocMsg {
+ BatchingAdapter& mAdapter;
+ BatchingStatus mBatchStatus;
+ inline MsgReportBatchStatus(BatchingAdapter& adapter,
+ BatchingStatus batchStatus) :
+ LocMsg(),
+ mAdapter(adapter),
+ mBatchStatus(batchStatus)
+ {
+ }
+ inline virtual ~MsgReportBatchStatus() {
+ }
+ inline virtual void proc() const {
+ std::list<uint32_t> tempList;
+ tempList.clear();
+ mAdapter.reportBatchStatusChange(mBatchStatus, tempList);
+ }
+ };
+
+ sendMsg(new MsgReportBatchStatus(*this, batchStatus));
+}
+
+void
+BatchingAdapter::startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions)
+{
+ if (mTripSessions.size() == 0) {
+ // if there is currenty no batching sessions interested in batch full event, then this
+ // new session will need to register for batch full event
+ if (0 == autoReportBatchingSessionsCount()) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_ENABLED);
+ }
+
+ // Assume start will be OK, remove session if not
+ saveBatchingSession(client, sessionId, batchingOptions);
+
+ mTripSessions[sessionId] = { 0, 0, 0, batchingOptions.minDistance,
+ batchingOptions.minInterval};
+ mLocApi->startOutdoorTripBatching(batchingOptions.minDistance,
+ batchingOptions.minInterval, getBatchingTimeout(), new LocApiResponse(*getContext(),
+ [this, client, sessionId, batchingOptions] (LocationError err) {
+ if (err == LOCATION_ERROR_SUCCESS) {
+ mOngoingTripDistance = batchingOptions.minDistance;
+ mOngoingTripTBFInterval = batchingOptions.minInterval;
+ LOC_LOGD("%s] New Trip started ...", __func__);
+ printTripReport();
+ } else {
+ eraseBatchingSession(client, sessionId);
+ mTripSessions.erase(sessionId);
+ // if we fail to start batching and we have already registered batch full event
+ // we need to undo that since no sessions are now interested in batch full event
+ if (0 == autoReportBatchingSessionsCount()) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+ }
+ reportResponse(client, err, sessionId);
+ }));
+ } else {
+ // query accumulated distance
+ mLocApi->queryAccumulatedTripDistance(
+ new LocApiResponseData<LocApiBatchData>(*getContext(),
+ [this, batchingOptions, sessionId, client]
+ (LocationError err, LocApiBatchData data) {
+ uint32_t accumulatedDistanceOngoingBatch = 0;
+ uint32_t numOfBatchedPositions = 0;
+ uint32_t ongoingTripDistance = mOngoingTripDistance;
+ uint32_t ongoingTripInterval = mOngoingTripTBFInterval;
+ bool needsRestart = false;
+
+ // check if TBF of new session is lesser than ongoing TBF interval
+ if (ongoingTripInterval > batchingOptions.minInterval) {
+ ongoingTripInterval = batchingOptions.minInterval;
+ needsRestart = true;
+ }
+ accumulatedDistanceOngoingBatch = data.accumulatedDistance;
+ numOfBatchedPositions = data.numOfBatchedPositions;
+ TripSessionStatus newTripSession = { accumulatedDistanceOngoingBatch, 0, 0,
+ batchingOptions.minDistance,
+ batchingOptions.minInterval};
+ if (err != LOCATION_ERROR_SUCCESS) {
+ // unable to query accumulated distance, assume remaining distance in
+ // ongoing batch is mongoingTripDistance.
+ if (batchingOptions.minDistance < ongoingTripDistance) {
+ ongoingTripDistance = batchingOptions.minDistance;
+ needsRestart = true;
+ }
+ } else {
+ // compute the remaining distance
+ uint32_t ongoing_trip_remaining_distance = ongoingTripDistance -
+ accumulatedDistanceOngoingBatch;
+
+ // check if new trip distance is lesser than the ongoing batch remaining distance
+ if (batchingOptions.minDistance < ongoing_trip_remaining_distance) {
+ ongoingTripDistance = batchingOptions.minDistance;
+ needsRestart = true;
+ } else if (needsRestart == true) {
+ // needsRestart is anyways true , may be because of lesser TBF of new session.
+ ongoingTripDistance = ongoing_trip_remaining_distance;
+ }
+ mTripSessions[sessionId] = newTripSession;
+ LOC_LOGD("%s] New Trip started ...", __func__);
+ printTripReport();
+ }
+
+ if (needsRestart) {
+ mOngoingTripDistance = ongoingTripDistance;
+ mOngoingTripTBFInterval = ongoingTripInterval;
+
+ // reset the accumulatedDistanceOngoingBatch for each session,
+ // and record the total accumulated distance so far for the session.
+ for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) {
+ TripSessionStatus &tripSessStatus = itt->second;
+ tripSessStatus.accumulatedDistanceOngoingBatch = 0;
+ tripSessStatus.accumulatedDistanceOnTripRestart =
+ tripSessStatus.accumulatedDistanceThisTrip;
+ }
+ mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval,
+ getBatchingTimeout(), new LocApiResponse(*getContext(),
+ [this, client, sessionId] (LocationError err) {
+ if (err != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGE("%s] New Trip restart failed!", __func__);
+ }
+ reportResponse(client, err, sessionId);
+ }));
+ } else {
+ reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
+ }
+ }));
+ }
+}
+
+void
+BatchingAdapter::stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId,
+ bool restartNeeded, const BatchingOptions& batchOptions)
+{
+ LocationError err = LOCATION_ERROR_SUCCESS;
+
+ if (mTripSessions.size() == 1) {
+ mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(),
+ [this, restartNeeded, client, sessionId, batchOptions]
+ (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ // if stopOutdoorTripBatching is success, unregister for batch full event if this
+ // was the last batching session that is interested in batch full event
+ if (1 == autoReportBatchingSessionsCount()) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+ }
+ stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions);
+ }));
+ return;
+ }
+
+ stopTripBatchingMultiplexCommon(err, client, sessionId, restartNeeded, batchOptions);
+}
+
+void
+BatchingAdapter::stopTripBatchingMultiplexCommon(LocationError err, LocationAPI* client,
+ uint32_t sessionId, bool restartNeeded, const BatchingOptions& batchOptions)
+{
+ auto itt = mTripSessions.find(sessionId);
+ TripSessionStatus tripSess = itt->second;
+ if (tripSess.tripTBFInterval == mOngoingTripTBFInterval) {
+ // trip with ongoing trip interval is stopped
+ mTripWithOngoingTBFDropped = true;
+ }
+
+ if (tripSess.tripDistance == mOngoingTripDistance) {
+ // trip with ongoing trip distance is stopped
+ mTripWithOngoingTripDistanceDropped = true;
+ }
+
+ mTripSessions.erase(sessionId);
+
+ if (mTripSessions.size() == 0) {
+ mOngoingTripDistance = 0;
+ mOngoingTripTBFInterval = 0;
+ } else {
+ restartTripBatching(true);
+ }
+
+ if (restartNeeded) {
+ eraseBatchingSession(client, sessionId);
+ if (batchOptions.batchingMode == BATCHING_MODE_ROUTINE ||
+ batchOptions.batchingMode == BATCHING_MODE_NO_AUTO_REPORT) {
+ startBatching(client, sessionId, batchOptions);
+ } else if (batchOptions.batchingMode == BATCHING_MODE_TRIP) {
+ startTripBatchingMultiplex(client, sessionId, batchOptions);
+ }
+ }
+ reportResponse(client, err, sessionId);
+}
+
+
+void
+BatchingAdapter::restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist,
+ uint32_t numbatchedPos)
+{
+ // does batch need restart with new trip distance / TBF interval
+ uint32_t minRemainingDistance = 0;
+ uint32_t minTBFInterval = 0;
+
+ // if no more trips left, stop the ongoing trip
+ if (mTripSessions.size() == 0) {
+ mLocApi->stopOutdoorTripBatching(true, new LocApiResponse(*getContext(),
+ [] (LocationError /*err*/) {}));
+ mOngoingTripDistance = 0;
+ mOngoingTripTBFInterval = 0;
+ // unregister for batch full event if there are no more
+ // batching session that is interested in batch full event
+ if (0 == autoReportBatchingSessionsCount()) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_BATCH_FULL,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+ return;
+ }
+
+ // record the min trip distance and min tbf interval of all ongoing sessions
+ for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) {
+
+ TripSessionStatus tripSessStatus = itt->second;
+
+ if ((minRemainingDistance == 0) ||
+ (minRemainingDistance > (tripSessStatus.tripDistance
+ - tripSessStatus.accumulatedDistanceThisTrip))) {
+ minRemainingDistance = tripSessStatus.tripDistance -
+ tripSessStatus.accumulatedDistanceThisTrip;
+ }
+
+ if ((minTBFInterval == 0) ||
+ (minTBFInterval > tripSessStatus.tripTBFInterval)) {
+ minTBFInterval = tripSessStatus.tripTBFInterval;
+ }
+ }
+
+ mLocApi->queryAccumulatedTripDistance(
+ new LocApiResponseData<LocApiBatchData>(*getContext(),
+ [this, queryAccumulatedDistance, minRemainingDistance, minTBFInterval, accDist,
+ numbatchedPos] (LocationError /*err*/, LocApiBatchData data) {
+ bool needsRestart = false;
+
+ uint32_t ongoingTripDistance = mOngoingTripDistance;
+ uint32_t ongoingTripInterval = mOngoingTripTBFInterval;
+ uint32_t accumulatedDistance = accDist;
+ uint32_t numOfBatchedPositions = numbatchedPos;
+
+ if (queryAccumulatedDistance) {
+ accumulatedDistance = data.accumulatedDistance;
+ numOfBatchedPositions = data.numOfBatchedPositions;
+ }
+
+ if ((!mTripWithOngoingTripDistanceDropped) &&
+ (ongoingTripDistance - accumulatedDistance != 0)) {
+ // if ongoing trip is already not completed still,
+ // check the min distance against the remaining distance
+ if (minRemainingDistance <
+ (ongoingTripDistance - accumulatedDistance)) {
+ ongoingTripDistance = minRemainingDistance;
+ needsRestart = true;
+ }
+ } else if (minRemainingDistance != 0) {
+ // else if ongoing trip is already completed / dropped,
+ // use the minRemainingDistance of ongoing sessions
+ ongoingTripDistance = minRemainingDistance;
+ needsRestart = true;
+ }
+
+ if ((minTBFInterval < ongoingTripInterval) ||
+ ((minTBFInterval != ongoingTripInterval) &&
+ (mTripWithOngoingTBFDropped))) {
+ ongoingTripInterval = minTBFInterval;
+ needsRestart = true;
+ }
+
+ if (needsRestart) {
+ mLocApi->reStartOutdoorTripBatching(ongoingTripDistance, ongoingTripInterval,
+ getBatchingTimeout(), new LocApiResponse(*getContext(),
+ [this, accumulatedDistance, ongoingTripDistance, ongoingTripInterval]
+ (LocationError err) {
+
+ if (err == LOCATION_ERROR_SUCCESS) {
+ for(auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) {
+ TripSessionStatus &tripSessStatus = itt->second;
+ tripSessStatus.accumulatedDistanceThisTrip =
+ tripSessStatus.accumulatedDistanceOnTripRestart +
+ (accumulatedDistance -
+ tripSessStatus.accumulatedDistanceOngoingBatch);
+
+ tripSessStatus.accumulatedDistanceOngoingBatch = 0;
+ tripSessStatus.accumulatedDistanceOnTripRestart =
+ tripSessStatus.accumulatedDistanceThisTrip;
+ }
+
+ mOngoingTripDistance = ongoingTripDistance;
+ mOngoingTripTBFInterval = ongoingTripInterval;
+ }
+ }));
+ }
+ }));
+}
+
+void
+BatchingAdapter::printTripReport()
+{
+ IF_LOC_LOGD {
+ LOC_LOGD("Ongoing Trip Distance = %u, Ongoing Trip TBF Interval = %u",
+ mOngoingTripDistance, mOngoingTripTBFInterval);
+
+ for (auto itt = mTripSessions.begin(); itt != mTripSessions.end(); itt++) {
+ TripSessionStatus tripSessStatus = itt->second;
+
+ LOC_LOGD("tripDistance:%u tripTBFInterval:%u"
+ " trip accumulated Distance:%u"
+ " trip accumualted distance ongoing batch:%u"
+ " trip accumulated distance on trip restart %u \r\n",
+ tripSessStatus.tripDistance, tripSessStatus.tripTBFInterval,
+ tripSessStatus.accumulatedDistanceThisTrip,
+ tripSessStatus.accumulatedDistanceOngoingBatch,
+ tripSessStatus.accumulatedDistanceOnTripRestart);
+ }
+ }
+}
diff --git a/gps/batching/BatchingAdapter.h b/gps/batching/BatchingAdapter.h
new file mode 100644
index 0000000..66f7c5f
--- /dev/null
+++ b/gps/batching/BatchingAdapter.h
@@ -0,0 +1,152 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef BATCHING_ADAPTER_H
+#define BATCHING_ADAPTER_H
+
+#include <LocAdapterBase.h>
+#include <LocContext.h>
+#include <LocationAPI.h>
+#include <map>
+
+using namespace loc_core;
+
+class BatchingAdapter : public LocAdapterBase {
+
+ /* ==== BATCHING ======================================================================= */
+ typedef struct {
+ uint32_t accumulatedDistanceOngoingBatch;
+ uint32_t accumulatedDistanceThisTrip;
+ uint32_t accumulatedDistanceOnTripRestart;
+ uint32_t tripDistance;
+ uint32_t tripTBFInterval;
+ } TripSessionStatus;
+ typedef std::map<uint32_t, TripSessionStatus> TripSessionStatusMap;
+ typedef std::map<LocationSessionKey, BatchingOptions> BatchingSessionMap;
+
+ BatchingSessionMap mBatchingSessions;
+ TripSessionStatusMap mTripSessions;
+ uint32_t mOngoingTripDistance;
+ uint32_t mOngoingTripTBFInterval;
+ bool mTripWithOngoingTBFDropped;
+ bool mTripWithOngoingTripDistanceDropped;
+
+ void startTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions);
+ void stopTripBatchingMultiplex(LocationAPI* client, uint32_t sessionId,
+ bool restartNeeded,
+ const BatchingOptions& batchOptions);
+ inline void stopTripBatchingMultiplex(LocationAPI* client, uint32_t id) {
+ BatchingOptions batchOptions;
+ stopTripBatchingMultiplex(client, id, false, batchOptions);
+ };
+ void stopTripBatchingMultiplexCommon(LocationError err,
+ LocationAPI* client,
+ uint32_t sessionId,
+ bool restartNeeded,
+ const BatchingOptions& batchOptions);
+ void restartTripBatching(bool queryAccumulatedDistance, uint32_t accDist = 0,
+ uint32_t numbatchedPos = 0);
+ void printTripReport();
+
+ /* ==== CONFIGURATION ================================================================== */
+ uint32_t mBatchingTimeout;
+ uint32_t mBatchingAccuracy;
+ size_t mBatchSize;
+ size_t mTripBatchSize;
+
+protected:
+
+ /* ==== CLIENT ========================================================================= */
+ virtual void updateClientsEventMask();
+ virtual void stopClientSessions(LocationAPI* client);
+
+public:
+ BatchingAdapter();
+ virtual ~BatchingAdapter() {}
+
+ /* ==== SSR ============================================================================ */
+ /* ======== EVENTS ====(Called from QMI Thread)========================================= */
+ virtual void handleEngineUpEvent();
+ /* ======== UTILITIES ================================================================== */
+ void restartSessions();
+
+ /* ==== BATCHING ======================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ uint32_t startBatchingCommand(LocationAPI* client, BatchingOptions &batchOptions);
+ void updateBatchingOptionsCommand(
+ LocationAPI* client, uint32_t id, BatchingOptions& batchOptions);
+ void stopBatchingCommand(LocationAPI* client, uint32_t id);
+ void getBatchedLocationsCommand(LocationAPI* client, uint32_t id, size_t count);
+ /* ======== RESPONSES ================================================================== */
+ void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId);
+ /* ======== UTILITIES ================================================================== */
+ bool hasBatchingCallback(LocationAPI* client);
+ bool isBatchingSession(LocationAPI* client, uint32_t sessionId);
+ bool isTripSession(uint32_t sessionId);
+ void saveBatchingSession(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions);
+ void eraseBatchingSession(LocationAPI* client, uint32_t sessionId);
+ uint32_t autoReportBatchingSessionsCount();
+ void startBatching(LocationAPI* client, uint32_t sessionId,
+ const BatchingOptions& batchingOptions);
+ void stopBatching(LocationAPI* client, uint32_t sessionId, bool restartNeeded,
+ const BatchingOptions& batchOptions);
+ void stopBatching(LocationAPI* client, uint32_t sessionId) {
+ BatchingOptions batchOptions;
+ stopBatching(client, sessionId, false, batchOptions);
+ };
+
+ /* ==== REPORTS ======================================================================== */
+ /* ======== EVENTS ====(Called from QMI Thread)========================================= */
+ void reportLocationsEvent(const Location* locations, size_t count,
+ BatchingMode batchingMode);
+ void reportCompletedTripsEvent(uint32_t accumulatedDistance);
+ void reportBatchStatusChangeEvent(BatchingStatus batchStatus);
+ /* ======== UTILITIES ================================================================== */
+ void reportLocations(Location* locations, size_t count, BatchingMode batchingMode);
+ void reportBatchStatusChange(BatchingStatus batchStatus,
+ std::list<uint32_t> & completedTripsList);
+
+ /* ==== CONFIGURATION ================================================================== */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void readConfigCommand();
+ void setConfigCommand();
+ /* ======== UTILITIES ================================================================== */
+ void setBatchSize(size_t batchSize) { mBatchSize = batchSize; }
+ size_t getBatchSize() { return mBatchSize; }
+ void setTripBatchSize(size_t batchSize) { mTripBatchSize = batchSize; }
+ size_t getTripBatchSize() { return mTripBatchSize; }
+ void setBatchingTimeout(uint32_t batchingTimeout) { mBatchingTimeout = batchingTimeout; }
+ uint32_t getBatchingTimeout() { return mBatchingTimeout; }
+ void setBatchingAccuracy(uint32_t accuracy) { mBatchingAccuracy = accuracy; }
+ uint32_t getBatchingAccuracy() { return mBatchingAccuracy; }
+
+};
+
+#endif /* BATCHING_ADAPTER_H */
diff --git a/gps/batching/Makefile.am b/gps/batching/Makefile.am
new file mode 100644
index 0000000..d5cba39
--- /dev/null
+++ b/gps/batching/Makefile.am
@@ -0,0 +1,44 @@
+AM_CFLAGS = \
+ $(GPSUTILS_CFLAGS) \
+ $(LOCCORE_CFLAGS) \
+ -I./ \
+ -std=c++1y \
+ -D__func__=__PRETTY_FUNCTION__ \
+ -fno-short-enums
+
+ACLOCAL_AMFLAGS = -I m4
+
+requiredlibs = \
+ $(GPSUTILS_LIBS) \
+ $(LOCCORE_LIBS) \
+ -llog
+
+h_sources = \
+ BatchingAdapter.h
+
+libbatching_la_SOURCES = \
+ location_batching.cpp \
+ BatchingAdapter.cpp
+
+if USE_GLIB
+libbatching_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
+libbatching_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread $(requiredlibs) @GLIB_LIBS@ -shared -version-info 1:0:0
+libbatching_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
+else
+libbatching_la_CFLAGS = $(AM_CFLAGS)
+libbatching_la_LDFLAGS = -Wl,-z,defs -lpthread $(requiredlibs) -shared -version-info 1:0:0
+libbatching_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+library_include_HEADERS = $(h_sources)
+
+library_includedir = $(pkgincludedir)
+
+#Create and Install libraries
+lib_LTLIBRARIES = libbatching.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = location-batching.pc
+sysconf_DATA = $(WORKSPACE)/hardware/qcom/gps/etc/flp.conf
+EXTRA_DIST = $(pkgconfig_DATA)
+
diff --git a/gps/batching/configure.ac b/gps/batching/configure.ac
new file mode 100644
index 0000000..4ca4998
--- /dev/null
+++ b/gps/batching/configure.ac
@@ -0,0 +1,74 @@
+# configure.ac -- Autoconf script for gps location-batching
+#
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the gps location-batching package version 1.0.0
+AC_INIT([location-batching],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# Verifies the --srcdir is correct by checking for the path
+AC_CONFIG_SRCDIR([Makefile.am])
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
+AC_SUBST([GPSUTILS_CFLAGS])
+AC_SUBST([GPSUTILS_LIBS])
+
+PKG_CHECK_MODULES([LOCCORE], [loc-core])
+AC_SUBST([LOCCORE_CFLAGS])
+AC_SUBST([LOCCORE_LIBS])
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x$with_locpla_includes" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ location-batching.pc
+ ])
+
+AC_OUTPUT
diff --git a/gps/batching/location-batching.pc.in b/gps/batching/location-batching.pc.in
new file mode 100644
index 0000000..da1fbf4
--- /dev/null
+++ b/gps/batching/location-batching.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: location-batching
+Description: QTI GPS Batching
+Version: @VERSION
+Libs: -L${libdir} -lbatching
+Cflags: -I${includedir}/location-batching
diff --git a/gps/batching/location_batching.cpp b/gps/batching/location_batching.cpp
new file mode 100644
index 0000000..571da72
--- /dev/null
+++ b/gps/batching/location_batching.cpp
@@ -0,0 +1,134 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "BatchingAdapter.h"
+#include "location_interface.h"
+
+static BatchingAdapter* gBatchingAdapter = NULL;
+
+static void initialize();
+static void deinitialize();
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks);
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+static void requestCapabilities(LocationAPI* client);
+
+static uint32_t startBatching(LocationAPI* client, BatchingOptions&);
+static void stopBatching(LocationAPI* client, uint32_t id);
+static void updateBatchingOptions(LocationAPI* client, uint32_t id, BatchingOptions&);
+static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count);
+
+static const BatchingInterface gBatchingInterface = {
+ sizeof(BatchingInterface),
+ initialize,
+ deinitialize,
+ addClient,
+ removeClient,
+ requestCapabilities,
+ startBatching,
+ stopBatching,
+ updateBatchingOptions,
+ getBatchedLocations
+};
+
+#ifndef DEBUG_X86
+extern "C" const BatchingInterface* getBatchingInterface()
+#else
+const BatchingInterface* getBatchingInterface()
+#endif // DEBUG_X86
+{
+ return &gBatchingInterface;
+}
+
+static void initialize()
+{
+ if (NULL == gBatchingAdapter) {
+ gBatchingAdapter = new BatchingAdapter();
+ }
+}
+
+static void deinitialize()
+{
+ if (NULL != gBatchingAdapter) {
+ delete gBatchingAdapter;
+ gBatchingAdapter = NULL;
+ }
+}
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->addClientCommand(client, callbacks);
+ }
+}
+
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->removeClientCommand(client, rmClientCb);
+ }
+}
+
+static void requestCapabilities(LocationAPI* client)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->requestCapabilitiesCommand(client);
+ }
+}
+
+static uint32_t startBatching(LocationAPI* client, BatchingOptions &batchOptions)
+{
+ if (NULL != gBatchingAdapter) {
+ return gBatchingAdapter->startBatchingCommand(client, batchOptions);
+ } else {
+ return 0;
+ }
+}
+
+static void stopBatching(LocationAPI* client, uint32_t id)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->stopBatchingCommand(client, id);
+ }
+}
+
+static void updateBatchingOptions(
+ LocationAPI* client, uint32_t id, BatchingOptions& batchOptions)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->updateBatchingOptionsCommand(client, id, batchOptions);
+ }
+}
+
+static void getBatchedLocations(LocationAPI* client, uint32_t id, size_t count)
+{
+ if (NULL != gBatchingAdapter) {
+ gBatchingAdapter->getBatchedLocationsCommand(client, id, count);
+ }
+}
+
diff --git a/gps/configure.ac b/gps/configure.ac
new file mode 100644
index 0000000..2a44051
--- /dev/null
+++ b/gps/configure.ac
@@ -0,0 +1,87 @@
+# configure.ac -- Autoconf script for gps loc_hal
+#
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the gps loc-hal package version 1.0.0
+AC_INIT([loc-hal],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# Verifies the --srcdir is correct by checking for the path
+AC_CONFIG_SRCDIR([Makefile.am])
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
+AC_SUBST([GPSUTILS_CFLAGS])
+AC_SUBST([GPSUTILS_LIBS])
+
+PKG_CHECK_MODULES([LOCCORE], [loc-core])
+AC_SUBST([LOCCORE_CFLAGS])
+AC_SUBST([LOCCORE_LIBS])
+
+AC_ARG_WITH([core_includes],
+ AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+ [Specify the location of the core headers]),
+ [core_incdir=$withval],
+ with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x$with_locpla_includes" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_SUBST([CPPFLAGS])
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ gnss/Makefile \
+ loc-hal.pc \
+ ])
+
+AC_OUTPUT
diff --git a/gps/core/Android.bp b/gps/core/Android.bp
new file mode 100644
index 0000000..ee8e807
--- /dev/null
+++ b/gps/core/Android.bp
@@ -0,0 +1,56 @@
+
+cc_library_shared {
+
+ name: "libloc_core",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ "libcutils",
+ "libgps.utils",
+ "libdl",
+ "liblog",
+ ],
+
+ srcs: [
+ "LocApiBase.cpp",
+ "LocAdapterBase.cpp",
+ "ContextBase.cpp",
+ "LocContext.cpp",
+ "loc_core_log.cpp",
+ "data-items/DataItemsFactoryProxy.cpp",
+ "SystemStatusOsObserver.cpp",
+ "SystemStatus.cpp",
+ ],
+
+ cflags: [
+ "-fno-short-enums",
+ "-D_ANDROID_",
+ ] + GNSS_CFLAGS,
+
+ local_include_dirs: [
+ "data-items",
+ "observer",
+ ],
+
+ header_libs: [
+ "libutils_headers",
+ "libgps.utils_headers",
+ "libloc_pla_headers",
+ "liblocation_api_headers",
+ ],
+
+}
+
+cc_library_headers {
+
+ name: "libloc_core_headers",
+ vendor: true,
+ export_include_dirs: ["."] + [
+ "data-items",
+ "observer",
+ ],
+}
diff --git a/gps/core/ContextBase.cpp b/gps/core/ContextBase.cpp
new file mode 100644
index 0000000..87e98dc
--- /dev/null
+++ b/gps/core/ContextBase.cpp
@@ -0,0 +1,384 @@
+/* Copyright (c) 2011-2014,2016-2017,2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_CtxBase"
+
+#include <dlfcn.h>
+#include <unistd.h>
+#include <ContextBase.h>
+#include <msg_q.h>
+#include <loc_target.h>
+#include <loc_pla.h>
+#include <loc_log.h>
+
+namespace loc_core {
+
+#define SLL_LOC_API_LIB_NAME "libsynergy_loc_api.so"
+#define LOC_APIV2_0_LIB_NAME "libloc_api_v02.so"
+#define IS_SS5_HW_ENABLED 1
+
+loc_gps_cfg_s_type ContextBase::mGps_conf {};
+loc_sap_cfg_s_type ContextBase::mSap_conf {};
+bool ContextBase::sIsEngineCapabilitiesKnown = false;
+uint64_t ContextBase::sSupportedMsgMask = 0;
+bool ContextBase::sGnssMeasurementSupported = false;
+uint8_t ContextBase::sFeaturesSupported[MAX_FEATURE_LENGTH];
+GnssNMEARptRate ContextBase::sNmeaReportRate = GNSS_NMEA_REPORT_RATE_NHZ;
+LocationCapabilitiesMask ContextBase::sQwesFeatureMask = 0;
+
+const loc_param_s_type ContextBase::mGps_conf_table[] =
+{
+ {"GPS_LOCK", &mGps_conf.GPS_LOCK, NULL, 'n'},
+ {"SUPL_VER", &mGps_conf.SUPL_VER, NULL, 'n'},
+ {"LPP_PROFILE", &mGps_conf.LPP_PROFILE, NULL, 'n'},
+ {"A_GLONASS_POS_PROTOCOL_SELECT", &mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT, NULL, 'n'},
+ {"LPPE_CP_TECHNOLOGY", &mGps_conf.LPPE_CP_TECHNOLOGY, NULL, 'n'},
+ {"LPPE_UP_TECHNOLOGY", &mGps_conf.LPPE_UP_TECHNOLOGY, NULL, 'n'},
+ {"AGPS_CERT_WRITABLE_MASK", &mGps_conf.AGPS_CERT_WRITABLE_MASK, NULL, 'n'},
+ {"SUPL_MODE", &mGps_conf.SUPL_MODE, NULL, 'n'},
+ {"SUPL_ES", &mGps_conf.SUPL_ES, NULL, 'n'},
+ {"INTERMEDIATE_POS", &mGps_conf.INTERMEDIATE_POS, NULL, 'n'},
+ {"ACCURACY_THRES", &mGps_conf.ACCURACY_THRES, NULL, 'n'},
+ {"NMEA_PROVIDER", &mGps_conf.NMEA_PROVIDER, NULL, 'n'},
+ {"NMEA_REPORT_RATE", &mGps_conf.NMEA_REPORT_RATE, NULL, 's'},
+ {"CAPABILITIES", &mGps_conf.CAPABILITIES, NULL, 'n'},
+ {"XTRA_SERVER_1", &mGps_conf.XTRA_SERVER_1, NULL, 's'},
+ {"XTRA_SERVER_2", &mGps_conf.XTRA_SERVER_2, NULL, 's'},
+ {"XTRA_SERVER_3", &mGps_conf.XTRA_SERVER_3, NULL, 's'},
+ {"USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL",
+ &mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, NULL, 'n'},
+ {"AGPS_CONFIG_INJECT", &mGps_conf.AGPS_CONFIG_INJECT, NULL, 'n'},
+ {"EXTERNAL_DR_ENABLED", &mGps_conf.EXTERNAL_DR_ENABLED, NULL, 'n'},
+ {"SUPL_HOST", &mGps_conf.SUPL_HOST, NULL, 's'},
+ {"SUPL_PORT", &mGps_conf.SUPL_PORT, NULL, 'n'},
+ {"MODEM_TYPE", &mGps_conf.MODEM_TYPE, NULL, 'n' },
+ {"MO_SUPL_HOST", &mGps_conf.MO_SUPL_HOST, NULL, 's' },
+ {"MO_SUPL_PORT", &mGps_conf.MO_SUPL_PORT, NULL, 'n' },
+ {"CONSTRAINED_TIME_UNCERTAINTY_ENABLED",
+ &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED, NULL, 'n'},
+ {"CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD",
+ &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD, NULL, 'f'},
+ {"CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET",
+ &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET, NULL, 'n'},
+ {"POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED",
+ &mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED, NULL, 'n'},
+ {"PROXY_APP_PACKAGE_NAME", &mGps_conf.PROXY_APP_PACKAGE_NAME, NULL, 's' },
+ {"CP_MTLR_ES", &mGps_conf.CP_MTLR_ES, NULL, 'n' },
+ {"GNSS_DEPLOYMENT", &mGps_conf.GNSS_DEPLOYMENT, NULL, 'n'},
+ {"CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED",
+ &mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED, NULL, 'n'},
+ {"NMEA_TAG_BLOCK_GROUPING_ENABLED", &mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED, NULL, 'n'},
+ {"NI_SUPL_DENY_ON_NFW_LOCKED", &mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED, NULL, 'n'},
+ {"ENABLE_NMEA_PRINT", &mGps_conf.ENABLE_NMEA_PRINT, NULL, 'n'}
+};
+
+const loc_param_s_type ContextBase::mSap_conf_table[] =
+{
+ {"GYRO_BIAS_RANDOM_WALK", &mSap_conf.GYRO_BIAS_RANDOM_WALK, &mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID, 'f'},
+ {"ACCEL_RANDOM_WALK_SPECTRAL_DENSITY", &mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, &mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"ANGLE_RANDOM_WALK_SPECTRAL_DENSITY", &mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, &mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"RATE_RANDOM_WALK_SPECTRAL_DENSITY", &mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, &mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY", &mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY, &mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'},
+ {"SENSOR_ACCEL_BATCHES_PER_SEC", &mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, NULL, 'n'},
+ {"SENSOR_ACCEL_SAMPLES_PER_BATCH", &mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, NULL, 'n'},
+ {"SENSOR_GYRO_BATCHES_PER_SEC", &mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC, NULL, 'n'},
+ {"SENSOR_GYRO_SAMPLES_PER_BATCH", &mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, NULL, 'n'},
+ {"SENSOR_ACCEL_BATCHES_PER_SEC_HIGH", &mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, NULL, 'n'},
+ {"SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH", &mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, NULL, 'n'},
+ {"SENSOR_GYRO_BATCHES_PER_SEC_HIGH", &mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, NULL, 'n'},
+ {"SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH", &mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, NULL, 'n'},
+ {"SENSOR_CONTROL_MODE", &mSap_conf.SENSOR_CONTROL_MODE, NULL, 'n'},
+ {"SENSOR_ALGORITHM_CONFIG_MASK", &mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK, NULL, 'n'}
+};
+
+void ContextBase::readConfig()
+{
+ static bool confReadDone = false;
+ if (!confReadDone) {
+ confReadDone = true;
+ /*Defaults for gps.conf*/
+ mGps_conf.INTERMEDIATE_POS = 0;
+ mGps_conf.ACCURACY_THRES = 0;
+ mGps_conf.NMEA_PROVIDER = 0;
+ mGps_conf.GPS_LOCK = GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
+ mGps_conf.SUPL_VER = 0x10000;
+ mGps_conf.SUPL_MODE = 0x1;
+ mGps_conf.SUPL_ES = 0;
+ mGps_conf.CP_MTLR_ES = 0;
+ mGps_conf.SUPL_HOST[0] = 0;
+ mGps_conf.SUPL_PORT = 0;
+ mGps_conf.CAPABILITIES = 0x7;
+ /* LTE Positioning Profile configuration is disable by default*/
+ mGps_conf.LPP_PROFILE = 0;
+ /*By default no positioning protocol is selected on A-GLONASS system*/
+ mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = 0;
+ /*Use emergency PDN by default*/
+ mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = 1;
+ /* By default no LPPe CP technology is enabled*/
+ mGps_conf.LPPE_CP_TECHNOLOGY = 0;
+ /* By default no LPPe UP technology is enabled*/
+ mGps_conf.LPPE_UP_TECHNOLOGY = 0;
+ /* By default we use unknown modem type*/
+ mGps_conf.MODEM_TYPE = 2;
+
+ /*Defaults for sap.conf*/
+ mSap_conf.GYRO_BIAS_RANDOM_WALK = 0;
+ mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC = 2;
+ mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH = 5;
+ mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC = 2;
+ mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH = 5;
+ mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH = 4;
+ mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH = 25;
+ mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH = 4;
+ mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH = 25;
+ mSap_conf.SENSOR_CONTROL_MODE = 0; /* AUTO */
+ mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK = 0; /* INS Disabled = FALSE*/
+ /* Values MUST be set by OEMs in configuration for sensor-assisted
+ navigation to work. There are NO default values */
+ mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY = 0;
+ mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID = 0;
+ mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+ mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0;
+
+ /* None of the 10 slots for agps certificates are writable by default */
+ mGps_conf.AGPS_CERT_WRITABLE_MASK = 0;
+
+ /* inject supl config to modem with config values from config.xml or gps.conf, default 1 */
+ mGps_conf.AGPS_CONFIG_INJECT = 1;
+
+ /* default configuration value of constrained time uncertainty mode:
+ feature disabled, time uncertainty threshold defined by modem,
+ and unlimited power budget */
+#ifdef FEATURE_AUTOMOTIVE
+ mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 1;
+#else
+ mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 0;
+#endif
+ mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD = 0.0;
+ mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET = 0;
+
+ /* default configuration value of position assisted clock estimator mode */
+ mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED = 0;
+ /* default configuration QTI GNSS H/W */
+ mGps_conf.GNSS_DEPLOYMENT = 0;
+ mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0;
+ /* default NMEA Tag Block Grouping is disabled */
+ mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED = 0;
+ /* default configuration for NI_SUPL_DENY_ON_NFW_LOCKED */
+ mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED = 1;
+ /* By default NMEA Printing is disabled */
+ mGps_conf.ENABLE_NMEA_PRINT = 0;
+
+ UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table);
+ UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table);
+
+ if (strncmp(mGps_conf.NMEA_REPORT_RATE, "1HZ", sizeof(mGps_conf.NMEA_REPORT_RATE)) == 0) {
+ /* NMEA reporting is configured at 1Hz*/
+ sNmeaReportRate = GNSS_NMEA_REPORT_RATE_1HZ;
+ } else {
+ sNmeaReportRate = GNSS_NMEA_REPORT_RATE_NHZ;
+ }
+ LOC_LOGI("%s] GNSS Deployment: %s", __FUNCTION__,
+ ((mGps_conf.GNSS_DEPLOYMENT == 1) ? "SS5" :
+ ((mGps_conf.GNSS_DEPLOYMENT == 2) ? "QFUSION" : "QGNSS")));
+
+ switch (getTargetGnssType(loc_get_target())) {
+ case GNSS_GSS:
+ case GNSS_AUTO:
+ // For APQ targets, MSA/MSB capabilities should be reset
+ mGps_conf.CAPABILITIES &= ~(LOC_GPS_CAPABILITY_MSA | LOC_GPS_CAPABILITY_MSB);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+uint32_t ContextBase::getCarrierCapabilities() {
+ #define carrierMSA (uint32_t)0x2
+ #define carrierMSB (uint32_t)0x1
+ #define gpsConfMSA (uint32_t)0x4
+ #define gpsConfMSB (uint32_t)0x2
+ uint32_t capabilities = mGps_conf.CAPABILITIES;
+ if ((mGps_conf.SUPL_MODE & carrierMSA) != carrierMSA) {
+ capabilities &= ~gpsConfMSA;
+ }
+ if ((mGps_conf.SUPL_MODE & carrierMSB) != carrierMSB) {
+ capabilities &= ~gpsConfMSB;
+ }
+
+ LOC_LOGV("getCarrierCapabilities: CAPABILITIES %x, SUPL_MODE %x, carrier capabilities %x",
+ mGps_conf.CAPABILITIES, mGps_conf.SUPL_MODE, capabilities);
+ return capabilities;
+}
+
+LBSProxyBase* ContextBase::getLBSProxy(const char* libName)
+{
+ LBSProxyBase* proxy = NULL;
+ LOC_LOGD("%s:%d]: getLBSProxy libname: %s\n", __func__, __LINE__, libName);
+ void* lib = dlopen(libName, RTLD_NOW);
+
+ if ((void*)NULL != lib) {
+ getLBSProxy_t* getter = (getLBSProxy_t*)dlsym(lib, "getLBSProxy");
+ if (NULL != getter) {
+ proxy = (*getter)();
+ }
+ }
+ else
+ {
+ LOC_LOGW("%s:%d]: FAILED TO LOAD libname: %s\n", __func__, __LINE__, libName);
+ }
+ if (NULL == proxy) {
+ proxy = new LBSProxyBase();
+ }
+ LOC_LOGD("%s:%d]: Exiting\n", __func__, __LINE__);
+ return proxy;
+}
+
+LocApiBase* ContextBase::createLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask)
+{
+ LocApiBase* locApi = NULL;
+ const char* libname = LOC_APIV2_0_LIB_NAME;
+
+ // Check the target
+ if (TARGET_NO_GNSS != loc_get_target()){
+
+ if (NULL == (locApi = mLBSProxy->getLocApi(exMask, this))) {
+ void *handle = NULL;
+
+ if (IS_SS5_HW_ENABLED == mGps_conf.GNSS_DEPLOYMENT) {
+ libname = SLL_LOC_API_LIB_NAME;
+ }
+
+ if ((handle = dlopen(libname, RTLD_NOW)) != NULL) {
+ LOC_LOGD("%s:%d]: %s is present", __func__, __LINE__, libname);
+ getLocApi_t* getter = (getLocApi_t*) dlsym(handle, "getLocApi");
+ if (getter != NULL) {
+ LOC_LOGD("%s:%d]: getter is not NULL of %s", __func__,
+ __LINE__, libname);
+ locApi = (*getter)(exMask, this);
+ }
+ }
+ // only RPC is the option now
+ else {
+ LOC_LOGD("%s:%d]: libloc_api_v02.so is NOT present. Trying RPC",
+ __func__, __LINE__);
+ handle = dlopen("libloc_api-rpc-qc.so", RTLD_NOW);
+ if (NULL != handle) {
+ getLocApi_t* getter = (getLocApi_t*) dlsym(handle, "getLocApi");
+ if (NULL != getter) {
+ LOC_LOGD("%s:%d]: getter is not NULL in RPC", __func__,
+ __LINE__);
+ locApi = (*getter)(exMask, this);
+ }
+ }
+ }
+ }
+ }
+
+ // locApi could still be NULL at this time
+ // we would then create a dummy one
+ if (NULL == locApi) {
+ locApi = new LocApiBase(exMask, this);
+ }
+
+ return locApi;
+}
+
+ContextBase::ContextBase(const MsgTask* msgTask,
+ LOC_API_ADAPTER_EVENT_MASK_T exMask,
+ const char* libName) :
+ mLBSProxy(getLBSProxy(libName)),
+ mMsgTask(msgTask),
+ mLocApi(createLocApi(exMask)),
+ mLocApiProxy(mLocApi->getLocApiProxy())
+{
+}
+
+void ContextBase::setEngineCapabilities(uint64_t supportedMsgMask,
+ uint8_t *featureList, bool gnssMeasurementSupported) {
+
+ if (ContextBase::sIsEngineCapabilitiesKnown == false) {
+ ContextBase::sSupportedMsgMask = supportedMsgMask;
+ ContextBase::sGnssMeasurementSupported = gnssMeasurementSupported;
+ if (featureList != NULL) {
+ memcpy((void *)ContextBase::sFeaturesSupported,
+ (void *)featureList, sizeof(ContextBase::sFeaturesSupported));
+ }
+
+ /* */
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+ static uint8_t isSapModeKnown = 0;
+
+ if (!isSapModeKnown) {
+ /* Check if SAP is PREMIUM_ENV_AIDING in izat.conf */
+ char conf_feature_sap[LOC_MAX_PARAM_STRING];
+ loc_param_s_type izat_conf_feature_table[] =
+ {
+ { "SAP", &conf_feature_sap, &isSapModeKnown, 's' }
+ };
+ UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izat_conf_feature_table);
+
+ /* Disable this feature if SAP is not PREMIUM_ENV_AIDING in izat.conf */
+ if (strcmp(conf_feature_sap, "PREMIUM_ENV_AIDING") != 0) {
+ uint8_t arrayIndex = LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION >> 3;
+ uint8_t bitPos = LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION & 7;
+
+ if (arrayIndex < MAX_FEATURE_LENGTH) {
+ /* To disable the feature we need to reset the bit on the "bitPos"
+ position, so shift a "1" to the left by "bitPos" */
+ ContextBase::sFeaturesSupported[arrayIndex] &= ~(1 << bitPos);
+ }
+ }
+ }
+ }
+ ContextBase::sIsEngineCapabilitiesKnown = true;
+ }
+}
+
+
+bool ContextBase::isFeatureSupported(uint8_t featureVal)
+{
+ uint8_t arrayIndex = featureVal >> 3;
+ uint8_t bitPos = featureVal & 7;
+
+ if (arrayIndex >= MAX_FEATURE_LENGTH) return false;
+ return ((ContextBase::sFeaturesSupported[arrayIndex] >> bitPos ) & 0x1);
+}
+
+bool ContextBase::gnssConstellationConfig() {
+ return sGnssMeasurementSupported;
+}
+
+}
diff --git a/gps/core/ContextBase.h b/gps/core/ContextBase.h
new file mode 100644
index 0000000..34cad60
--- /dev/null
+++ b/gps/core/ContextBase.h
@@ -0,0 +1,385 @@
+/* Copyright (c) 2011-2017, 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_CONTEXT_BASE__
+#define __LOC_CONTEXT_BASE__
+
+#include <stdbool.h>
+#include <ctype.h>
+#include <MsgTask.h>
+#include <LocApiBase.h>
+#include <LBSProxyBase.h>
+#include <loc_cfg.h>
+#ifdef NO_UNORDERED_SET_OR_MAP
+ #include <map>
+#else
+ #include <unordered_map>
+#endif
+
+/* GPS.conf support */
+/* NOTE: the implementaiton of the parser casts number
+ fields to 32 bit. To ensure all 'n' fields working,
+ they must all be 32 bit fields. */
+typedef struct loc_gps_cfg_s
+{
+ uint32_t INTERMEDIATE_POS;
+ uint32_t ACCURACY_THRES;
+ uint32_t SUPL_VER;
+ uint32_t SUPL_MODE;
+ uint32_t SUPL_ES;
+ uint32_t CAPABILITIES;
+ uint32_t LPP_PROFILE;
+ char XTRA_SERVER_1[LOC_MAX_PARAM_STRING];
+ char XTRA_SERVER_2[LOC_MAX_PARAM_STRING];
+ char XTRA_SERVER_3[LOC_MAX_PARAM_STRING];
+ uint32_t USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL;
+ uint32_t NMEA_PROVIDER;
+ char NMEA_REPORT_RATE[LOC_MAX_PARAM_NAME];
+ GnssConfigGpsLock GPS_LOCK;
+ uint32_t A_GLONASS_POS_PROTOCOL_SELECT;
+ uint32_t AGPS_CERT_WRITABLE_MASK;
+ uint32_t AGPS_CONFIG_INJECT;
+ uint32_t LPPE_CP_TECHNOLOGY;
+ uint32_t LPPE_UP_TECHNOLOGY;
+ uint32_t EXTERNAL_DR_ENABLED;
+ char SUPL_HOST[LOC_MAX_PARAM_STRING];
+ uint32_t SUPL_PORT;
+ uint32_t MODEM_TYPE;
+ char MO_SUPL_HOST[LOC_MAX_PARAM_STRING];
+ uint32_t MO_SUPL_PORT;
+ uint32_t CONSTRAINED_TIME_UNCERTAINTY_ENABLED;
+ double CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
+ uint32_t CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
+ uint32_t POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED;
+ char PROXY_APP_PACKAGE_NAME[LOC_MAX_PARAM_STRING];
+ uint32_t CP_MTLR_ES;
+ uint32_t GNSS_DEPLOYMENT;
+ uint32_t CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED;
+ uint32_t NI_SUPL_DENY_ON_NFW_LOCKED;
+ uint32_t ENABLE_NMEA_PRINT;
+ uint32_t NMEA_TAG_BLOCK_GROUPING_ENABLED;
+} loc_gps_cfg_s_type;
+
+/* NOTE: the implementation of the parser casts number
+ fields to 32 bit. To ensure all 'n' fields working,
+ they must all be 32 bit fields. */
+/* Meanwhile, *_valid fields are 8 bit fields, and 'f'
+ fields are double. Rigid as they are, it is the
+ the status quo, until the parsing mechanism is
+ changed, that is. */
+typedef struct
+{
+ uint8_t GYRO_BIAS_RANDOM_WALK_VALID;
+ double GYRO_BIAS_RANDOM_WALK;
+ uint32_t SENSOR_ACCEL_BATCHES_PER_SEC;
+ uint32_t SENSOR_ACCEL_SAMPLES_PER_BATCH;
+ uint32_t SENSOR_GYRO_BATCHES_PER_SEC;
+ uint32_t SENSOR_GYRO_SAMPLES_PER_BATCH;
+ uint32_t SENSOR_ACCEL_BATCHES_PER_SEC_HIGH;
+ uint32_t SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH;
+ uint32_t SENSOR_GYRO_BATCHES_PER_SEC_HIGH;
+ uint32_t SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH;
+ uint32_t SENSOR_CONTROL_MODE;
+ uint32_t SENSOR_ALGORITHM_CONFIG_MASK;
+ uint8_t ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID;
+ double ACCEL_RANDOM_WALK_SPECTRAL_DENSITY;
+ uint8_t ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID;
+ double ANGLE_RANDOM_WALK_SPECTRAL_DENSITY;
+ uint8_t RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID;
+ double RATE_RANDOM_WALK_SPECTRAL_DENSITY;
+ uint8_t VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID;
+ double VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY;
+} loc_sap_cfg_s_type;
+
+using namespace loc_util;
+
+namespace loc_core {
+
+class LocAdapterBase;
+
+class ContextBase {
+ static LBSProxyBase* getLBSProxy(const char* libName);
+ LocApiBase* createLocApi(LOC_API_ADAPTER_EVENT_MASK_T excludedMask);
+ static const loc_param_s_type mGps_conf_table[];
+ static const loc_param_s_type mSap_conf_table[];
+protected:
+ const LBSProxyBase* mLBSProxy;
+ const MsgTask* mMsgTask;
+ LocApiBase* mLocApi;
+ LocApiProxyBase *mLocApiProxy;
+
+public:
+ ContextBase(const MsgTask* msgTask,
+ LOC_API_ADAPTER_EVENT_MASK_T exMask,
+ const char* libName);
+ inline virtual ~ContextBase() {
+ if (nullptr != mLocApi) {
+ mLocApi->destroy();
+ mLocApi = nullptr;
+ }
+ if (nullptr != mLBSProxy) {
+ delete mLBSProxy;
+ mLBSProxy = nullptr;
+ }
+ }
+
+ inline const MsgTask* getMsgTask() { return mMsgTask; }
+ inline LocApiBase* getLocApi() { return mLocApi; }
+ inline LocApiProxyBase* getLocApiProxy() { return mLocApiProxy; }
+ inline bool hasAgpsExtendedCapabilities() { return mLBSProxy->hasAgpsExtendedCapabilities(); }
+ inline bool hasNativeXtraClient() { return mLBSProxy->hasNativeXtraClient(); }
+ inline void modemPowerVote(bool power) const { return mLBSProxy->modemPowerVote(power); }
+ inline IzatDevId_t getIzatDevId() const {
+ return mLBSProxy->getIzatDevId();
+ }
+ inline void sendMsg(const LocMsg *msg) { getMsgTask()->sendMsg(msg); }
+
+ static loc_gps_cfg_s_type mGps_conf;
+ static loc_sap_cfg_s_type mSap_conf;
+ static bool sIsEngineCapabilitiesKnown;
+ static uint64_t sSupportedMsgMask;
+ static uint8_t sFeaturesSupported[MAX_FEATURE_LENGTH];
+ static bool sGnssMeasurementSupported;
+ static GnssNMEARptRate sNmeaReportRate;
+ static LocationCapabilitiesMask sQwesFeatureMask;
+
+ void readConfig();
+ static uint32_t getCarrierCapabilities();
+ void setEngineCapabilities(uint64_t supportedMsgMask,
+ uint8_t *featureList, bool gnssMeasurementSupported);
+
+ static inline bool isEngineCapabilitiesKnown() {
+ return sIsEngineCapabilitiesKnown;
+ }
+
+ static inline bool isMessageSupported(LocCheckingMessagesID msgID) {
+
+ // confirm if msgID is not larger than the number of bits in
+ // mSupportedMsg
+ if ((uint64_t)msgID > (sizeof(sSupportedMsgMask) << 3)) {
+ return false;
+ } else {
+ uint32_t messageChecker = 1 << msgID;
+ return (messageChecker & sSupportedMsgMask) == messageChecker;
+ }
+ }
+
+ /*
+ Check if a feature is supported
+ */
+ static bool isFeatureSupported(uint8_t featureVal);
+
+ /*
+ Check if gnss measurement is supported
+ */
+ static bool gnssConstellationConfig();
+
+ /*
+ set QWES feature status info
+ */
+ static inline void setQwesFeatureStatus(
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
+ std::unordered_map<LocationQwesFeatureType, bool>::const_iterator itr;
+ static LocationQwesFeatureType locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_MAX];
+ for (itr = featureMap.begin(); itr != featureMap.end(); ++itr) {
+ LOC_LOGi("Feature : %d isValid: %d", itr->first, itr->second);
+ locQwesFeatType[itr->first] = itr->second;
+ switch (itr->first) {
+ case LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_SV_EPH:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_PPE:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_PPE;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_PPE;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_QDR2:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR2;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR2;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_QDR3:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_QDR3;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_QDR3;
+ }
+ break;
+ case LOCATION_QWES_FEATURE_TYPE_VPE:
+ if (itr->second) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_VPE;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_VPE;
+ }
+ break;
+ }
+ }
+
+ // Set CV2X basic when time freq and tunc is set
+ // CV2X_BASIC = LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY &
+ // LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY
+
+ // Set CV2X premium when time freq and tunc is set
+ // CV2X_PREMIUM = CV2X_BASIC & LOCATION_QWES_FEATURE_TYPE_QDR3 &
+ // LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE
+
+ bool cv2xBasicEnabled = (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY]) &&
+ (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY]);
+ bool cv2xPremiumEnabled = cv2xBasicEnabled &&
+ (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_QDR3]) &&
+ (1 == locQwesFeatType[LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE]);
+
+ LOC_LOGd("CV2X_BASIC:%d, CV2X_PREMIUM:%d", cv2xBasicEnabled, cv2xPremiumEnabled);
+ if (cv2xBasicEnabled) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC;
+ }
+ if (cv2xPremiumEnabled) {
+ sQwesFeatureMask |= LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM;
+ } else {
+ sQwesFeatureMask &= ~LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM;
+ }
+ }
+
+ /*
+ get QWES feature status info
+ */
+ static inline LocationCapabilitiesMask getQwesFeatureStatus() {
+ return (ContextBase::sQwesFeatureMask);
+ }
+
+
+};
+
+struct LocApiResponse: LocMsg {
+ private:
+ ContextBase& mContext;
+ std::function<void (LocationError err)> mProcImpl;
+ inline virtual void proc() const {
+ mProcImpl(mLocationError);
+ }
+ protected:
+ LocationError mLocationError;
+ public:
+ inline LocApiResponse(ContextBase& context,
+ std::function<void (LocationError err)> procImpl ) :
+ mContext(context), mProcImpl(procImpl) {}
+
+ void returnToSender(const LocationError err) {
+ mLocationError = err;
+ mContext.sendMsg(this);
+ }
+};
+
+struct LocApiCollectiveResponse: LocMsg {
+ private:
+ ContextBase& mContext;
+ std::function<void (std::vector<LocationError> errs)> mProcImpl;
+ inline virtual void proc() const {
+ mProcImpl(mLocationErrors);
+ }
+ protected:
+ std::vector<LocationError> mLocationErrors;
+ public:
+ inline LocApiCollectiveResponse(ContextBase& context,
+ std::function<void (std::vector<LocationError> errs)> procImpl ) :
+ mContext(context), mProcImpl(procImpl) {}
+ inline virtual ~LocApiCollectiveResponse() {
+ }
+
+ void returnToSender(std::vector<LocationError>& errs) {
+ mLocationErrors = errs;
+ mContext.sendMsg(this);
+ }
+};
+
+
+template <typename DATA>
+struct LocApiResponseData: LocMsg {
+ private:
+ ContextBase& mContext;
+ std::function<void (LocationError err, DATA data)> mProcImpl;
+ inline virtual void proc() const {
+ mProcImpl(mLocationError, mData);
+ }
+ protected:
+ LocationError mLocationError;
+ DATA mData;
+ public:
+ inline LocApiResponseData(ContextBase& context,
+ std::function<void (LocationError err, DATA data)> procImpl ) :
+ mContext(context), mProcImpl(procImpl) {}
+
+ void returnToSender(const LocationError err, const DATA data) {
+ mLocationError = err;
+ mData = data;
+ mContext.sendMsg(this);
+ }
+};
+
+
+} // namespace loc_core
+
+#endif //__LOC_CONTEXT_BASE__
diff --git a/gps/core/EngineHubProxyBase.h b/gps/core/EngineHubProxyBase.h
new file mode 100644
index 0000000..468a8f0
--- /dev/null
+++ b/gps/core/EngineHubProxyBase.h
@@ -0,0 +1,160 @@
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef ENGINE_HUB_PROXY_BASE_H
+#define ENGINE_HUB_PROXY_BASE_H
+#ifdef NO_UNORDERED_SET_OR_MAP
+ #include <map>
+#else
+ #include <unordered_map>
+#endif
+
+namespace loc_core {
+
+using namespace loc_util;
+
+class EngineHubProxyBase {
+public:
+ inline EngineHubProxyBase() {
+ }
+ inline virtual ~EngineHubProxyBase() {}
+
+ // gnss session related functions
+ inline virtual bool gnssStartFix() {
+ return false;
+ }
+
+ inline virtual bool gnssStopFix() {
+ return false;
+ }
+
+ inline virtual bool gnssSetFixMode(const LocPosMode &params) {
+ (void) params;
+ return false;
+ }
+
+ inline virtual bool gnssDeleteAidingData(const GnssAidingData &aidingData) {
+ (void) aidingData;
+ return false;
+ }
+
+ // GNSS reports
+ inline virtual bool gnssReportPosition(const UlpLocation &location,
+ const GpsLocationExtended &locationExtended,
+ enum loc_sess_status status) {
+ (void) location;
+ (void) locationExtended;
+ (void) status;
+ return false;
+ }
+
+ inline virtual bool gnssReportSv(const GnssSvNotification& svNotify) {
+ (void) svNotify;
+ return false;
+ }
+
+ inline virtual bool gnssReportSvMeasurement(const GnssSvMeasurementSet& svMeasurementSet) {
+ (void) svMeasurementSet;
+ return false;
+ }
+
+ inline virtual bool gnssReportSvPolynomial(const GnssSvPolynomial& svPolynomial) {
+ (void) svPolynomial;
+ return false;
+ }
+
+ inline virtual bool gnssReportSvEphemeris(const GnssSvEphemerisReport& svEphemeris) {
+ (void) svEphemeris;
+ return false;
+ }
+
+ inline virtual bool gnssReportSystemInfo(const LocationSystemInfo& systemInfo) {
+ (void) systemInfo;
+ return false;
+ }
+
+ inline virtual bool gnssReportKlobucharIonoModel(const GnssKlobucharIonoModel& ionoModel) {
+ (void) ionoModel;
+ return false;
+ }
+
+ inline virtual bool gnssReportAdditionalSystemInfo(
+ const GnssAdditionalSystemInfo& additionalSystemInfo) {
+ (void) additionalSystemInfo;
+ return false;
+ }
+
+ inline virtual bool configLeverArm(const LeverArmConfigInfo& configInfo) {
+ (void) configInfo;
+ return false;
+ }
+
+ inline virtual bool configDeadReckoningEngineParams(
+ const DeadReckoningEngineConfig& dreConfig) {
+ (void) dreConfig;
+ return false;
+ }
+
+ inline virtual bool configEngineRunState(
+ PositioningEngineMask engType, LocEngineRunState engState) {
+ (void) engType;
+ (void) engState;
+ return false;
+ }
+};
+
+typedef std::function<void(int count, EngineLocationInfo* locationArr)>
+ GnssAdapterReportEnginePositionsEventCb;
+
+typedef std::function<void(const GnssSvNotification& svNotify,
+ bool fromEngineHub)>
+ GnssAdapterReportSvEventCb;
+
+typedef std::function<void(const GnssAidingDataSvMask& svDataMask)>
+ GnssAdapterReqAidingDataCb;
+
+typedef std::function<void(bool nHzNeeded, bool nHzMeasNeeded)>
+ GnssAdapterUpdateNHzRequirementCb;
+
+typedef std::function<void(const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)>
+ GnssAdapterUpdateQwesFeatureStatusCb;
+
+// potential parameters: message queue: MsgTask * msgTask;
+// callback function to report back dr and ppe position and sv report
+typedef EngineHubProxyBase* (getEngHubProxyFn)(
+ const MsgTask * msgTask,
+ IOsObserver* osObserver,
+ GnssAdapterReportEnginePositionsEventCb positionEventCb,
+ GnssAdapterReportSvEventCb svEventCb,
+ GnssAdapterReqAidingDataCb reqAidingDataCb,
+ GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb,
+ GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb);
+
+} // namespace loc_core
+
+#endif // ENGINE_HUB_PROXY_BASE_H
diff --git a/gps/core/LBSProxyBase.h b/gps/core/LBSProxyBase.h
new file mode 100644
index 0000000..564c60b
--- /dev/null
+++ b/gps/core/LBSProxyBase.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef IZAT_PROXY_BASE_H
+#define IZAT_PROXY_BASE_H
+#include <gps_extended.h>
+
+namespace loc_core {
+
+class LocApiBase;
+class LocAdapterBase;
+class ContextBase;
+
+class LBSProxyBase {
+ friend class ContextBase;
+ inline virtual LocApiBase*
+ getLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask,
+ ContextBase* context) const {
+
+ (void)exMask;
+ (void)context;
+ return NULL;
+ }
+protected:
+ inline LBSProxyBase() {}
+public:
+ inline virtual ~LBSProxyBase() {}
+ inline virtual bool hasAgpsExtendedCapabilities() const { return false; }
+ inline virtual void modemPowerVote(bool power) const {
+
+ (void)power;
+ }
+ virtual void injectFeatureConfig(ContextBase* context) const {
+
+ (void)context;
+ }
+ inline virtual bool hasNativeXtraClient() const { return false; }
+ inline virtual IzatDevId_t getIzatDevId() const { return 0; }
+};
+
+typedef LBSProxyBase* (getLBSProxy_t)();
+
+} // namespace loc_core
+
+#endif // IZAT_PROXY_BASE_H
diff --git a/gps/core/LocAdapterBase.cpp b/gps/core/LocAdapterBase.cpp
new file mode 100644
index 0000000..95f2728
--- /dev/null
+++ b/gps/core/LocAdapterBase.cpp
@@ -0,0 +1,439 @@
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_LocAdapterBase"
+
+#include <dlfcn.h>
+#include <LocAdapterBase.h>
+#include <loc_target.h>
+#include <log_util.h>
+#include <LocAdapterProxyBase.h>
+
+namespace loc_core {
+
+// This is the top level class, so the constructor will
+// always gets called. Here we prepare for the default.
+// But if getLocApi(targetEnumType target) is overriden,
+// the right locApi should get created.
+LocAdapterBase::LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
+ ContextBase* context, bool isMaster,
+ LocAdapterProxyBase *adapterProxyBase,
+ bool waitForDoneInit) :
+ mIsMaster(isMaster), mEvtMask(mask), mContext(context),
+ mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase),
+ mMsgTask(context->getMsgTask()),
+ mIsEngineCapabilitiesKnown(ContextBase::sIsEngineCapabilitiesKnown)
+{
+ LOC_LOGd("waitForDoneInit: %d", waitForDoneInit);
+ if (!waitForDoneInit) {
+ mLocApi->addAdapter(this);
+ mAdapterAdded = true;
+ } else {
+ mAdapterAdded = false;
+ }
+}
+
+uint32_t LocAdapterBase::mSessionIdCounter(1);
+
+uint32_t LocAdapterBase::generateSessionId()
+{
+ if (++mSessionIdCounter == 0xFFFFFFFF)
+ mSessionIdCounter = 1;
+
+ return mSessionIdCounter;
+}
+
+void LocAdapterBase::handleEngineUpEvent()
+{
+ if (mLocAdapterProxyBase) {
+ mLocAdapterProxyBase->handleEngineUpEvent();
+ }
+}
+
+void LocAdapterBase::handleEngineDownEvent()
+{
+ if (mLocAdapterProxyBase) {
+ mLocAdapterProxyBase->handleEngineDownEvent();
+ }
+}
+
+void LocAdapterBase::
+ reportPositionEvent(const UlpLocation& location,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask,
+ GnssDataNotification* pDataNotify,
+ int msInWeek)
+{
+ if (mLocAdapterProxyBase != NULL) {
+ mLocAdapterProxyBase->reportPositionEvent((UlpLocation&)location,
+ (GpsLocationExtended&)locationExtended,
+ status,
+ loc_technology_mask);
+ } else {
+ DEFAULT_IMPL()
+ }
+}
+
+void LocAdapterBase::
+ reportSvEvent(const GnssSvNotification& /*svNotify*/,
+ bool /*fromEngineHub*/)
+DEFAULT_IMPL()
+
+void LocAdapterBase::
+ reportSvPolynomialEvent(GnssSvPolynomial &/*svPolynomial*/)
+DEFAULT_IMPL()
+
+void LocAdapterBase::
+ reportSvEphemerisEvent(GnssSvEphemerisReport &/*svEphemeris*/)
+DEFAULT_IMPL()
+
+
+void LocAdapterBase::
+ reportStatus(LocGpsStatusValue /*status*/)
+DEFAULT_IMPL()
+
+
+void LocAdapterBase::
+ reportNmeaEvent(const char* /*nmea*/, size_t /*length*/)
+DEFAULT_IMPL()
+
+void LocAdapterBase::
+ reportDataEvent(const GnssDataNotification& /*dataNotify*/,
+ int /*msInWeek*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+ reportXtraServer(const char* /*url1*/, const char* /*url2*/,
+ const char* /*url3*/, const int /*maxlength*/)
+DEFAULT_IMPL(false)
+
+void LocAdapterBase::
+ reportLocationSystemInfoEvent(const LocationSystemInfo& /*locationSystemInfo*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+ requestXtraData()
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ requestTime()
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ requestLocation()
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ requestATL(int /*connHandle*/, LocAGpsType /*agps_type*/,
+ LocApnTypeMask /*apn_type_mask*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ releaseATL(int /*connHandle*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ requestNiNotifyEvent(const GnssNiNotification &/*notify*/,
+ const void* /*data*/,
+ const LocInEmergency emergencyState)
+DEFAULT_IMPL(false)
+
+void LocAdapterBase::
+reportGnssMeasurementsEvent(const GnssMeasurements& /*gnssMeasurements*/,
+ int /*msInWeek*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+ reportWwanZppFix(LocGpsLocation &/*zppLoc*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ reportZppBestAvailableFix(LocGpsLocation& /*zppLoc*/,
+ GpsLocationExtended& /*location_extended*/, LocPosTechMask /*tech_mask*/)
+DEFAULT_IMPL(false)
+
+void LocAdapterBase::reportGnssSvIdConfigEvent(const GnssSvIdConfig& /*config*/)
+DEFAULT_IMPL()
+
+void LocAdapterBase::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& /*config*/)
+DEFAULT_IMPL()
+
+void LocAdapterBase::reportGnssConfigEvent(uint32_t, /* session id*/
+ const GnssConfig& /*gnssConfig*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+ requestOdcpiEvent(OdcpiRequestInfo& /*request*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ reportGnssEngEnergyConsumedEvent(uint64_t /*energyConsumedSinceFirstBoot*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ reportDeleteAidingDataEvent(GnssAidingData & /*aidingData*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& /*ionoModel*/)
+DEFAULT_IMPL(false)
+
+bool LocAdapterBase::
+ reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo& /*additionalSystemInfo*/)
+DEFAULT_IMPL(false)
+
+void LocAdapterBase::
+ reportNfwNotificationEvent(GnssNfwNotification& /*notification*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::geofenceBreachEvent(size_t /*count*/, uint32_t* /*hwIds*/, Location& /*location*/,
+ GeofenceBreachType /*breachType*/, uint64_t /*timestamp*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::geofenceStatusEvent(GeofenceStatusAvailable /*available*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::reportLocationsEvent(const Location* /*locations*/, size_t /*count*/,
+ BatchingMode /*batchingMode*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::reportCompletedTripsEvent(uint32_t /*accumulated_distance*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::reportBatchStatusChangeEvent(BatchingStatus /*batchStatus*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::reportPositionEvent(UlpLocation& /*location*/,
+ GpsLocationExtended& /*locationExtended*/,
+ enum loc_sess_status /*status*/,
+ LocPosTechMask /*loc_technology_mask*/)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ mClientData[client] = callbacks;
+ updateClientsEventMask();
+}
+
+void
+LocAdapterBase::eraseClient(LocationAPI* client)
+{
+ auto it = mClientData.find(client);
+ if (it != mClientData.end()) {
+ mClientData.erase(it);
+ }
+ updateClientsEventMask();
+}
+
+LocationCallbacks
+LocAdapterBase::getClientCallbacks(LocationAPI* client)
+{
+ LocationCallbacks callbacks = {};
+ auto it = mClientData.find(client);
+ if (it != mClientData.end()) {
+ callbacks = it->second;
+ }
+ return callbacks;
+}
+
+LocationCapabilitiesMask
+LocAdapterBase::getCapabilities()
+{
+ LocationCapabilitiesMask mask = 0;
+
+ if (isEngineCapabilitiesKnown()) {
+ // time based tracking always supported
+ mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
+ if (ContextBase::isMessageSupported(
+ LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){
+ mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
+ LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
+ }
+ if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
+ mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
+ }
+ if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
+ mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
+ }
+ // geofence always supported
+ mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
+ if (ContextBase::gnssConstellationConfig()) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
+ }
+ uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
+ if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
+ }
+ if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
+ mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+ mask |= LOCATION_CAPABILITIES_AGPM_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY)) {
+ mask |= LOCATION_CAPABILITIES_PRIVACY_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+ mask |= LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_ROBUST_LOCATION)) {
+ mask |= LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_EDGNSS)) {
+ mask |= LOCATION_CAPABILITIES_EDGNSS_BIT;
+ }
+ } else {
+ LOC_LOGE("%s]: attempt to get capabilities before they are known.", __func__);
+ }
+
+ return mask;
+}
+
+void
+LocAdapterBase::broadcastCapabilities(LocationCapabilitiesMask mask)
+{
+ for (auto clientData : mClientData) {
+ if (nullptr != clientData.second.capabilitiesCb) {
+ clientData.second.capabilitiesCb(mask);
+ }
+ }
+}
+
+void
+LocAdapterBase::updateClientsEventMask()
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::stopClientSessions(LocationAPI* client)
+DEFAULT_IMPL()
+
+void
+LocAdapterBase::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+ struct MsgAddClient : public LocMsg {
+ LocAdapterBase& mAdapter;
+ LocationAPI* mClient;
+ const LocationCallbacks mCallbacks;
+ inline MsgAddClient(LocAdapterBase& adapter,
+ LocationAPI* client,
+ const LocationCallbacks& callbacks) :
+ LocMsg(),
+ mAdapter(adapter),
+ mClient(client),
+ mCallbacks(callbacks) {}
+ inline virtual void proc() const {
+ mAdapter.saveClient(mClient, mCallbacks);
+ }
+ };
+
+ sendMsg(new MsgAddClient(*this, client, callbacks));
+}
+
+void
+LocAdapterBase::removeClientCommand(LocationAPI* client,
+ removeClientCompleteCallback rmClientCb)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+ struct MsgRemoveClient : public LocMsg {
+ LocAdapterBase& mAdapter;
+ LocationAPI* mClient;
+ removeClientCompleteCallback mRmClientCb;
+ inline MsgRemoveClient(LocAdapterBase& adapter,
+ LocationAPI* client,
+ removeClientCompleteCallback rmCb) :
+ LocMsg(),
+ mAdapter(adapter),
+ mClient(client),
+ mRmClientCb(rmCb){}
+ inline virtual void proc() const {
+ mAdapter.stopClientSessions(mClient);
+ mAdapter.eraseClient(mClient);
+ if (nullptr != mRmClientCb) {
+ (mRmClientCb)(mClient);
+ }
+ }
+ };
+
+ sendMsg(new MsgRemoveClient(*this, client, rmClientCb));
+}
+
+void
+LocAdapterBase::requestCapabilitiesCommand(LocationAPI* client)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgRequestCapabilities : public LocMsg {
+ LocAdapterBase& mAdapter;
+ LocationAPI* mClient;
+ inline MsgRequestCapabilities(LocAdapterBase& adapter,
+ LocationAPI* client) :
+ LocMsg(),
+ mAdapter(adapter),
+ mClient(client) {}
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgRequestCapabilities(*this));
+ return;
+ }
+ LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
+ if (callbacks.capabilitiesCb != nullptr) {
+ callbacks.capabilitiesCb(mAdapter.getCapabilities());
+ }
+ }
+ };
+
+ sendMsg(new MsgRequestCapabilities(*this, client));
+}
+
+void
+LocAdapterBase::reportLatencyInfoEvent(const GnssLatencyInfo& /*gnssLatencyInfo*/)
+DEFAULT_IMPL()
+
+bool LocAdapterBase::
+ reportQwesCapabilities(const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
+DEFAULT_IMPL(false)
+
+} // namespace loc_core
diff --git a/gps/core/LocAdapterBase.h b/gps/core/LocAdapterBase.h
new file mode 100644
index 0000000..51b2306
--- /dev/null
+++ b/gps/core/LocAdapterBase.h
@@ -0,0 +1,246 @@
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef LOC_API_ADAPTER_BASE_H
+#define LOC_API_ADAPTER_BASE_H
+
+#include <gps_extended.h>
+#include <ContextBase.h>
+#include <LocationAPI.h>
+#include <map>
+
+#define MIN_TRACKING_INTERVAL (100) // 100 msec
+
+typedef struct LocationSessionKey {
+ LocationAPI* client;
+ uint32_t id;
+ inline LocationSessionKey(LocationAPI* _client, uint32_t _id) :
+ client(_client), id(_id) {}
+} LocationSessionKey;
+inline bool operator <(LocationSessionKey const& left, LocationSessionKey const& right) {
+ return left.id < right.id || (left.id == right.id && left.client < right.client);
+}
+inline bool operator ==(LocationSessionKey const& left, LocationSessionKey const& right) {
+ return left.id == right.id && left.client == right.client;
+}
+inline bool operator !=(LocationSessionKey const& left, LocationSessionKey const& right) {
+ return left.id != right.id || left.client != right.client;
+}
+
+typedef void (*removeClientCompleteCallback)(LocationAPI* client);
+
+namespace loc_core {
+
+class LocAdapterProxyBase;
+
+class LocAdapterBase {
+private:
+ static uint32_t mSessionIdCounter;
+ const bool mIsMaster;
+ bool mIsEngineCapabilitiesKnown = false;
+
+protected:
+ LOC_API_ADAPTER_EVENT_MASK_T mEvtMask;
+ ContextBase* mContext;
+ LocApiBase* mLocApi;
+ LocAdapterProxyBase* mLocAdapterProxyBase;
+ const MsgTask* mMsgTask;
+ bool mAdapterAdded;
+
+ inline LocAdapterBase(const MsgTask* msgTask) :
+ mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL),
+ mLocAdapterProxyBase(NULL), mMsgTask(msgTask), mAdapterAdded(false) {}
+
+ /* ==== CLIENT ========================================================================= */
+ typedef std::map<LocationAPI*, LocationCallbacks> ClientDataMap;
+ ClientDataMap mClientData;
+ std::vector<LocMsg*> mPendingMsgs; // For temporal storage of msgs before Open is completed
+ /* ======== UTILITIES ================================================================== */
+ void saveClient(LocationAPI* client, const LocationCallbacks& callbacks);
+ void eraseClient(LocationAPI* client);
+ LocationCallbacks getClientCallbacks(LocationAPI* client);
+ LocationCapabilitiesMask getCapabilities();
+ void broadcastCapabilities(LocationCapabilitiesMask mask);
+ virtual void updateClientsEventMask();
+ virtual void stopClientSessions(LocationAPI* client);
+
+public:
+ inline virtual ~LocAdapterBase() { mLocApi->removeAdapter(this); }
+ // When waitForDoneInit is not specified or specified as false,
+ // handleEngineUpEvent may be called on the child adapter object from
+ // a different thread before the constructor of the child
+ // object finishes.
+ //
+ // If the handleEngineUpEvent relies on member variables of the constructor
+ // of the child adapter to be initialized first, we need to specify the
+ // waitForDoneInit to *TRUE* to delay handleEngineUpEvent to get called
+ // until when the child adapter finishes its initialization and notify
+ // LocAdapterBase via doneInit method.
+ LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
+ ContextBase* context, bool isMaster = false,
+ LocAdapterProxyBase *adapterProxyBase = NULL,
+ bool waitForDoneInit = false);
+
+ inline void doneInit() {
+ if (!mAdapterAdded) {
+ mLocApi->addAdapter(this);
+ mAdapterAdded = true;
+ }
+ }
+
+ inline LOC_API_ADAPTER_EVENT_MASK_T
+ checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const {
+ return mEvtMask & mask;
+ }
+
+ inline LOC_API_ADAPTER_EVENT_MASK_T getEvtMask() const {
+ return mEvtMask;
+ }
+
+ inline void sendMsg(const LocMsg* msg) const {
+ mMsgTask->sendMsg(msg);
+ }
+
+ inline void sendMsg(const LocMsg* msg) {
+ mMsgTask->sendMsg(msg);
+ }
+
+ inline void updateEvtMask(LOC_API_ADAPTER_EVENT_MASK_T event,
+ loc_registration_mask_status status)
+ {
+ switch(status) {
+ case (LOC_REGISTRATION_MASK_ENABLED):
+ mEvtMask = mEvtMask | event;
+ break;
+ case (LOC_REGISTRATION_MASK_DISABLED):
+ mEvtMask = mEvtMask &~ event;
+ break;
+ case (LOC_REGISTRATION_MASK_SET):
+ mEvtMask = event;
+ break;
+ }
+ mLocApi->updateEvtMask();
+ }
+
+ inline void updateNmeaMask(uint32_t mask)
+ {
+ mLocApi->updateNmeaMask(mask);
+ }
+
+ inline bool isFeatureSupported(uint8_t featureVal) {
+ return ContextBase::isFeatureSupported(featureVal);
+ }
+
+ static uint32_t generateSessionId();
+
+ inline bool isAdapterMaster() {
+ return mIsMaster;
+ }
+
+ inline bool isEngineCapabilitiesKnown() { return mIsEngineCapabilitiesKnown;}
+ inline void setEngineCapabilitiesKnown(bool value) { mIsEngineCapabilitiesKnown = value;}
+
+ virtual void handleEngineUpEvent();
+ virtual void handleEngineDownEvent();
+ virtual void reportPositionEvent(const UlpLocation& location,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask,
+ GnssDataNotification* pDataNotify = nullptr,
+ int msInWeek = -1);
+ virtual void reportEnginePositionsEvent(unsigned int count,
+ EngineLocationInfo* locationArr) {
+ (void)count;
+ (void)locationArr;
+ }
+ virtual void reportSvEvent(const GnssSvNotification& svNotify,
+ bool fromEngineHub=false);
+ virtual void reportDataEvent(const GnssDataNotification& dataNotify, int msInWeek);
+ virtual void reportNmeaEvent(const char* nmea, size_t length);
+ virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial);
+ virtual void reportSvEphemerisEvent(GnssSvEphemerisReport &svEphemeris);
+ virtual void reportStatus(LocGpsStatusValue status);
+ virtual bool reportXtraServer(const char* url1, const char* url2,
+ const char* url3, const int maxlength);
+ virtual void reportLocationSystemInfoEvent(const LocationSystemInfo& locationSystemInfo);
+
+ virtual bool requestXtraData();
+ virtual bool requestTime();
+ virtual bool requestLocation();
+ virtual bool requestATL(int connHandle, LocAGpsType agps_type,
+ LocApnTypeMask apn_type_mask);
+ virtual bool releaseATL(int connHandle);
+ virtual bool requestNiNotifyEvent(const GnssNiNotification &notify, const void* data,
+ const LocInEmergency emergencyState);
+ inline virtual bool isInSession() { return false; }
+ ContextBase* getContext() const { return mContext; }
+ virtual void reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
+ int msInWeek);
+ virtual bool reportWwanZppFix(LocGpsLocation &zppLoc);
+ virtual bool reportZppBestAvailableFix(LocGpsLocation &zppLoc,
+ GpsLocationExtended &location_extended, LocPosTechMask tech_mask);
+ virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config);
+ virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config);
+ virtual void reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig);
+ virtual bool requestOdcpiEvent(OdcpiRequestInfo& request);
+ virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
+ virtual bool reportDeleteAidingDataEvent(GnssAidingData &aidingData);
+ virtual bool reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& ionoModel);
+ virtual bool reportGnssAdditionalSystemInfoEvent(
+ GnssAdditionalSystemInfo& additionalSystemInfo);
+ virtual void reportNfwNotificationEvent(GnssNfwNotification& notification);
+
+ virtual void geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp);
+ virtual void geofenceStatusEvent(GeofenceStatusAvailable available);
+
+ virtual void reportPositionEvent(UlpLocation &location,
+ GpsLocationExtended &locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask);
+
+ virtual void reportLocationsEvent(const Location* locations, size_t count,
+ BatchingMode batchingMode);
+ virtual void reportCompletedTripsEvent(uint32_t accumulated_distance);
+ virtual void reportBatchStatusChangeEvent(BatchingStatus batchStatus);
+
+ /* ==== CLIENT ========================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks);
+ void removeClientCommand(LocationAPI* client,
+ removeClientCompleteCallback rmClientCb);
+ void requestCapabilitiesCommand(LocationAPI* client);
+
+ virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo);
+ virtual bool reportQwesCapabilities(
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap);
+};
+
+} // namespace loc_core
+
+#endif //LOC_API_ADAPTER_BASE_H
diff --git a/gps/core/LocAdapterProxyBase.h b/gps/core/LocAdapterProxyBase.h
new file mode 100644
index 0000000..727d424
--- /dev/null
+++ b/gps/core/LocAdapterProxyBase.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_ADAPTER_PROXY_BASE_H
+#define LOC_ADAPTER_PROXY_BASE_H
+
+#include <ContextBase.h>
+#include <gps_extended.h>
+
+namespace loc_core {
+
+class LocAdapterProxyBase {
+private:
+ LocAdapterBase *mLocAdapterBase;
+protected:
+ inline LocAdapterProxyBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
+ ContextBase* context, bool isMaster = false):
+ mLocAdapterBase(new LocAdapterBase(mask, context, isMaster, this)) {
+ }
+ inline virtual ~LocAdapterProxyBase() {
+ delete mLocAdapterBase;
+ }
+ inline void updateEvtMask(LOC_API_ADAPTER_EVENT_MASK_T event,
+ loc_registration_mask_status isEnabled) {
+ mLocAdapterBase->updateEvtMask(event,isEnabled);
+ }
+
+ inline uint32_t generateSessionId() {
+ return mLocAdapterBase->generateSessionId();
+ }
+public:
+ inline ContextBase* getContext() const {
+ return mLocAdapterBase->getContext();
+ }
+
+ inline virtual void handleEngineUpEvent() {};
+ inline virtual void handleEngineDownEvent() {};
+ inline virtual void reportPositionEvent(UlpLocation &location,
+ GpsLocationExtended &locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask) {
+ (void)location;
+ (void)locationExtended;
+ (void)status;
+ (void)loc_technology_mask;
+ }
+};
+
+} // namespace loc_core
+
+#endif //LOC_ADAPTER_PROXY_BASE_H
diff --git a/gps/core/LocApiBase.cpp b/gps/core/LocApiBase.cpp
new file mode 100644
index 0000000..6a0ff84
--- /dev/null
+++ b/gps/core/LocApiBase.cpp
@@ -0,0 +1,1069 @@
+/* Copyright (c) 2011-2014, 2016-2021 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0 //Define to enable LOGV
+#define LOG_TAG "LocSvc_LocApiBase"
+
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <gps_extended_c.h>
+#include <LocApiBase.h>
+#include <LocAdapterBase.h>
+#include <log_util.h>
+#include <LocContext.h>
+#include <loc_misc_utils.h>
+
+namespace loc_core {
+
+#define TO_ALL_LOCADAPTERS(call) TO_ALL_ADAPTERS(mLocAdapters, (call))
+#define TO_1ST_HANDLING_LOCADAPTERS(call) TO_1ST_HANDLING_ADAPTER(mLocAdapters, (call))
+
+int hexcode(char *hexstring, int string_size,
+ const char *data, int data_size)
+{
+ int i;
+ for (i = 0; i < data_size; i++)
+ {
+ char ch = data[i];
+ if (i*2 + 3 <= string_size)
+ {
+ snprintf(&hexstring[i*2], 3, "%02X", ch);
+ }
+ else {
+ break;
+ }
+ }
+ return i;
+}
+
+int decodeAddress(char *addr_string, int string_size,
+ const char *data, int data_size)
+{
+ const char addr_prefix = 0x91;
+ int i, idxOutput = 0;
+
+ if (!data || !addr_string) { return 0; }
+
+ if (data[0] != addr_prefix)
+ {
+ LOC_LOGW("decodeAddress: address prefix is not 0x%x but 0x%x", addr_prefix, data[0]);
+ addr_string[0] = '\0';
+ return 0; // prefix not correct
+ }
+
+ for (i = 1; i < data_size; i++)
+ {
+ unsigned char ch = data[i], low = ch & 0x0F, hi = ch >> 4;
+ if (low <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = low + '0'; }
+ if (hi <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = hi + '0'; }
+ }
+
+ addr_string[idxOutput] = '\0'; // Terminates the string
+
+ return idxOutput;
+}
+
+struct LocSsrMsg : public LocMsg {
+ LocApiBase* mLocApi;
+ inline LocSsrMsg(LocApiBase* locApi) :
+ LocMsg(), mLocApi(locApi)
+ {
+ locallog();
+ }
+ inline virtual void proc() const {
+ mLocApi->close();
+ if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask())) {
+ // Notify adapters that engine up after SSR
+ mLocApi->handleEngineUpEvent();
+ }
+ }
+ inline void locallog() const {
+ LOC_LOGV("LocSsrMsg");
+ }
+ inline virtual void log() const {
+ locallog();
+ }
+};
+
+struct LocOpenMsg : public LocMsg {
+ LocApiBase* mLocApi;
+ LocAdapterBase* mAdapter;
+ inline LocOpenMsg(LocApiBase* locApi, LocAdapterBase* adapter = nullptr) :
+ LocMsg(), mLocApi(locApi), mAdapter(adapter)
+ {
+ locallog();
+ }
+ inline virtual void proc() const {
+ if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask()) &&
+ nullptr != mAdapter) {
+ mAdapter->handleEngineUpEvent();
+ }
+ }
+ inline void locallog() const {
+ LOC_LOGv("LocOpen Mask: %" PRIx64 "\n", mLocApi->getEvtMask());
+ }
+ inline virtual void log() const {
+ locallog();
+ }
+};
+
+struct LocCloseMsg : public LocMsg {
+ LocApiBase* mLocApi;
+ inline LocCloseMsg(LocApiBase* locApi) :
+ LocMsg(), mLocApi(locApi)
+ {
+ locallog();
+ }
+ inline virtual void proc() const {
+ mLocApi->close();
+ }
+ inline void locallog() const {
+ }
+ inline virtual void log() const {
+ locallog();
+ }
+};
+
+MsgTask* LocApiBase::mMsgTask = nullptr;
+volatile int32_t LocApiBase::mMsgTaskRefCount = 0;
+
+LocApiBase::LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask,
+ ContextBase* context) :
+ mContext(context),
+ mMask(0), mExcludedMask(excludedMask)
+{
+ memset(mLocAdapters, 0, sizeof(mLocAdapters));
+
+ android_atomic_inc(&mMsgTaskRefCount);
+ if (nullptr == mMsgTask) {
+ mMsgTask = new MsgTask("LocApiMsgTask");
+ }
+}
+
+LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::getEvtMask()
+{
+ LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
+
+ TO_ALL_LOCADAPTERS(mask |= mLocAdapters[i]->getEvtMask());
+
+ return mask & ~mExcludedMask;
+}
+
+bool LocApiBase::isMaster()
+{
+ bool isMaster = false;
+
+ for (int i = 0;
+ !isMaster && i < MAX_ADAPTERS && NULL != mLocAdapters[i];
+ i++) {
+ isMaster |= mLocAdapters[i]->isAdapterMaster();
+ }
+ return isMaster;
+}
+
+bool LocApiBase::isInSession()
+{
+ bool inSession = false;
+
+ for (int i = 0;
+ !inSession && i < MAX_ADAPTERS && NULL != mLocAdapters[i];
+ i++) {
+ inSession = mLocAdapters[i]->isInSession();
+ }
+
+ return inSession;
+}
+
+bool LocApiBase::needReport(const UlpLocation& ulpLocation,
+ enum loc_sess_status status,
+ LocPosTechMask techMask)
+{
+ bool reported = false;
+
+ if (LOC_SESS_SUCCESS == status) {
+ // this is a final fix
+ LocPosTechMask mask =
+ LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID;
+ // it is a Satellite fix or a sensor fix
+ reported = (mask & techMask);
+ }
+ else if (LOC_SESS_INTERMEDIATE == status &&
+ LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS) {
+ // this is a intermediate fix and we accept intermediate
+
+ // it is NOT the case that
+ // there is inaccuracy; and
+ // we care about inaccuracy; and
+ // the inaccuracy exceeds our tolerance
+ reported = !((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ACCURACY) &&
+ (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
+ (ulpLocation.gpsLocation.accuracy > ContextBase::mGps_conf.ACCURACY_THRES));
+ }
+
+ return reported;
+}
+
+void LocApiBase::addAdapter(LocAdapterBase* adapter)
+{
+ for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) {
+ if (mLocAdapters[i] == NULL) {
+ mLocAdapters[i] = adapter;
+ sendMsg(new LocOpenMsg(this, adapter));
+ break;
+ }
+ }
+}
+
+void LocApiBase::removeAdapter(LocAdapterBase* adapter)
+{
+ for (int i = 0;
+ i < MAX_ADAPTERS && NULL != mLocAdapters[i];
+ i++) {
+ if (mLocAdapters[i] == adapter) {
+ mLocAdapters[i] = NULL;
+
+ // shift the rest of the adapters up so that the pointers
+ // in the array do not have holes. This should be more
+ // performant, because the array maintenance is much much
+ // less frequent than event handlings, which need to linear
+ // search all the adapters
+ int j = i;
+ while (++i < MAX_ADAPTERS && mLocAdapters[i] != NULL);
+
+ // i would be MAX_ADAPTERS or point to a NULL
+ i--;
+ // i now should point to a none NULL adapter within valid
+ // range although i could be equal to j, but it won't hurt.
+ // No need to check it, as it gains nothing.
+ mLocAdapters[j] = mLocAdapters[i];
+ // this makes sure that we exit the for loop
+ mLocAdapters[i] = NULL;
+
+ // if we have an empty list of adapters
+ if (0 == i) {
+ sendMsg(new LocCloseMsg(this));
+ } else {
+ // else we need to remove the bit
+ sendMsg(new LocOpenMsg(this));
+ }
+ }
+ }
+}
+
+void LocApiBase::updateEvtMask()
+{
+ sendMsg(new LocOpenMsg(this));
+}
+
+void LocApiBase::updateNmeaMask(uint32_t mask)
+{
+ struct LocSetNmeaMsg : public LocMsg {
+ LocApiBase* mLocApi;
+ uint32_t mMask;
+ inline LocSetNmeaMsg(LocApiBase* locApi, uint32_t mask) :
+ LocMsg(), mLocApi(locApi), mMask(mask)
+ {
+ locallog();
+ }
+ inline virtual void proc() const {
+ mLocApi->setNMEATypesSync(mMask);
+ }
+ inline void locallog() const {
+ LOC_LOGv("LocSyncNmea NmeaMask: %" PRIx32 "\n", mMask);
+ }
+ inline virtual void log() const {
+ locallog();
+ }
+ };
+
+ sendMsg(new LocSetNmeaMsg(this, mask));
+}
+
+void LocApiBase::handleEngineUpEvent()
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent());
+}
+
+void LocApiBase::handleEngineDownEvent()
+{ // This will take care of renegotiating the loc handle
+ sendMsg(new LocSsrMsg(this));
+
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineDownEvent());
+}
+
+void LocApiBase::reportPosition(UlpLocation& location,
+ GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask,
+ GnssDataNotification* pDataNotify,
+ int msInWeek)
+{
+ // print the location info before delivering
+ LOC_LOGD("flags: %d\n source: %d\n latitude: %f\n longitude: %f\n "
+ "altitude: %f\n speed: %f\n bearing: %f\n accuracy: %f\n "
+ "timestamp: %" PRId64 "\n"
+ "Session status: %d\n Technology mask: %u\n "
+ "SV used in fix (gps/glo/bds/gal/qzss) : \
+ (0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 ")",
+ location.gpsLocation.flags, location.position_source,
+ location.gpsLocation.latitude, location.gpsLocation.longitude,
+ location.gpsLocation.altitude, location.gpsLocation.speed,
+ location.gpsLocation.bearing, location.gpsLocation.accuracy,
+ location.gpsLocation.timestamp, status, loc_technology_mask,
+ locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask,
+ locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask,
+ locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask,
+ locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask,
+ locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask,
+ locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask);
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(
+ mLocAdapters[i]->reportPositionEvent(location, locationExtended,
+ status, loc_technology_mask,
+ pDataNotify, msInWeek)
+ );
+}
+
+void LocApiBase::reportWwanZppFix(LocGpsLocation &zppLoc)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportWwanZppFix(zppLoc));
+}
+
+void LocApiBase::reportZppBestAvailableFix(LocGpsLocation &zppLoc,
+ GpsLocationExtended &location_extended, LocPosTechMask tech_mask)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportZppBestAvailableFix(zppLoc,
+ location_extended, tech_mask));
+}
+
+void LocApiBase::requestOdcpi(OdcpiRequestInfo& request)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestOdcpiEvent(request));
+}
+
+void LocApiBase::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssEngEnergyConsumedEvent(
+ energyConsumedSinceFirstBoot));
+}
+
+void LocApiBase::reportDeleteAidingDataEvent(GnssAidingData& aidingData) {
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDeleteAidingDataEvent(aidingData));
+}
+
+void LocApiBase::reportKlobucharIonoModel(GnssKlobucharIonoModel & ionoModel) {
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportKlobucharIonoModelEvent(ionoModel));
+}
+
+void LocApiBase::reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo) {
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportGnssAdditionalSystemInfoEvent(
+ additionalSystemInfo));
+}
+
+void LocApiBase::sendNfwNotification(GnssNfwNotification& notification)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNfwNotificationEvent(notification));
+
+}
+
+void LocApiBase::reportSv(GnssSvNotification& svNotify)
+{
+ const char* constellationString[] = { "Unknown", "GPS", "SBAS", "GLONASS",
+ "QZSS", "BEIDOU", "GALILEO", "NAVIC" };
+
+ // print the SV info before delivering
+ LOC_LOGV("num sv: %u\n"
+ " sv: constellation svid cN0 basebandCN0"
+ " elevation azimuth flags",
+ svNotify.count);
+ for (size_t i = 0; i < svNotify.count && i < GNSS_SV_MAX; i++) {
+ if (svNotify.gnssSvs[i].type >
+ sizeof(constellationString) / sizeof(constellationString[0]) - 1) {
+ svNotify.gnssSvs[i].type = GNSS_SV_TYPE_UNKNOWN;
+ }
+ // Display what we report to clients
+ LOC_LOGV(" %03zu: %*s %02d %f %f %f %f %f 0x%02X 0x%2X",
+ i,
+ 13,
+ constellationString[svNotify.gnssSvs[i].type],
+ svNotify.gnssSvs[i].svId,
+ svNotify.gnssSvs[i].cN0Dbhz,
+ svNotify.gnssSvs[i].basebandCarrierToNoiseDbHz,
+ svNotify.gnssSvs[i].elevation,
+ svNotify.gnssSvs[i].azimuth,
+ svNotify.gnssSvs[i].carrierFrequencyHz,
+ svNotify.gnssSvs[i].gnssSvOptionsMask,
+ svNotify.gnssSvs[i].gnssSignalTypeMask);
+ }
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(
+ mLocAdapters[i]->reportSvEvent(svNotify)
+ );
+}
+
+void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(
+ mLocAdapters[i]->reportSvPolynomialEvent(svPolynomial)
+ );
+}
+
+void LocApiBase::reportSvEphemeris(GnssSvEphemerisReport & svEphemeris)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(
+ mLocAdapters[i]->reportSvEphemerisEvent(svEphemeris)
+ );
+}
+
+void LocApiBase::reportStatus(LocGpsStatusValue status)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportStatus(status));
+}
+
+void LocApiBase::reportData(GnssDataNotification& dataNotify, int msInWeek)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportDataEvent(dataNotify, msInWeek));
+}
+
+void LocApiBase::reportNmea(const char* nmea, int length)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNmeaEvent(nmea, length));
+}
+
+void LocApiBase::reportXtraServer(const char* url1, const char* url2,
+ const char* url3, const int maxlength)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportXtraServer(url1, url2, url3, maxlength));
+
+}
+
+void LocApiBase::reportLocationSystemInfo(const LocationSystemInfo& locationSystemInfo)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationSystemInfoEvent(locationSystemInfo));
+}
+
+void LocApiBase::reportQwesCapabilities
+(
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportQwesCapabilities(featureMap));
+}
+void LocApiBase::requestXtraData()
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestXtraData());
+}
+
+void LocApiBase::requestTime()
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestTime());
+}
+
+void LocApiBase::requestLocation()
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestLocation());
+}
+
+void LocApiBase::requestATL(int connHandle, LocAGpsType agps_type,
+ LocApnTypeMask apn_type_mask)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(
+ mLocAdapters[i]->requestATL(connHandle, agps_type, apn_type_mask));
+}
+
+void LocApiBase::releaseATL(int connHandle)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->releaseATL(connHandle));
+}
+
+void LocApiBase::requestNiNotify(GnssNiNotification &notify, const void* data,
+ const LocInEmergency emergencyState)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_1ST_HANDLING_LOCADAPTERS(
+ mLocAdapters[i]->requestNiNotifyEvent(notify,
+ data,
+ emergencyState));
+}
+
+void* LocApiBase :: getSibling()
+ DEFAULT_IMPL(NULL)
+
+LocApiProxyBase* LocApiBase :: getLocApiProxy()
+ DEFAULT_IMPL(NULL)
+
+void LocApiBase::reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek)
+{
+ // loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementsEvent(gnssMeasurements, msInWeek));
+}
+
+void LocApiBase::reportGnssSvIdConfig(const GnssSvIdConfig& config)
+{
+ // Print the config
+ LOC_LOGv("gloBlacklistSvMask: %" PRIu64 ", bdsBlacklistSvMask: %" PRIu64 ",\n"
+ "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64 ",\n"
+ "navicBlacklistSvMask: %" PRIu64,
+ config.gloBlacklistSvMask, config.bdsBlacklistSvMask,
+ config.qzssBlacklistSvMask, config.galBlacklistSvMask, config.navicBlacklistSvMask);
+
+ // Loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvIdConfigEvent(config));
+}
+
+void LocApiBase::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
+{
+ // Print the config
+ LOC_LOGv("blacklistedMask: %" PRIu64 ", enabledMask: %" PRIu64,
+ config.blacklistedSvTypesMask, config.enabledSvTypesMask);
+
+ // Loop through adapters, and deliver to all adapters.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvTypeConfigEvent(config));
+}
+
+void LocApiBase::geofenceBreach(size_t count, uint32_t* hwIds, Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceBreachEvent(count, hwIds, location, breachType,
+ timestamp));
+}
+
+void LocApiBase::geofenceStatus(GeofenceStatusAvailable available)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceStatusEvent(available));
+}
+
+void LocApiBase::reportDBTPosition(UlpLocation &location, GpsLocationExtended &locationExtended,
+ enum loc_sess_status status, LocPosTechMask loc_technology_mask)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportPositionEvent(location, locationExtended, status,
+ loc_technology_mask));
+}
+
+void LocApiBase::reportLocations(Location* locations, size_t count, BatchingMode batchingMode)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationsEvent(locations, count, batchingMode));
+}
+
+void LocApiBase::reportCompletedTrips(uint32_t accumulated_distance)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportCompletedTripsEvent(accumulated_distance));
+}
+
+void LocApiBase::handleBatchStatusEvent(BatchingStatus batchStatus)
+{
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportBatchStatusChangeEvent(batchStatus));
+}
+
+void LocApiBase::reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssConfigEvent(sessionId, gnssConfig));
+}
+
+void LocApiBase::reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo)
+{
+ // loop through adapters, and deliver to the first handling adapter.
+ TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLatencyInfoEvent(gnssLatencyInfo));
+}
+
+enum loc_api_adapter_err LocApiBase::
+ open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/)
+DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
+
+enum loc_api_adapter_err LocApiBase::
+ close()
+DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
+
+void LocApiBase::startFix(const LocPosMode& /*posMode*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::stopFix(LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ deleteAidingData(const GnssAidingData& /*data*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/,
+ bool /*onDemandCpi*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ injectPosition(const Location& /*location*/, bool /*onDemandCpi*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ injectPosition(const GnssLocationInfoNotification & /*locationInfo*/, bool /*onDemandCpi*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, uint32_t /*apnLen*/,
+ AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/,
+ LocApnTypeMask /*mask*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ atlCloseStatus(int /*handle*/, int /*is_succ*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+ setServerSync(const char* /*url*/, int /*len*/, LocServerType /*type*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+LocationError LocApiBase::
+ setServerSync(unsigned int /*ip*/, int /*port*/, LocServerType /*type*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::
+ informNiResponse(GnssNiResponse /*userResponse*/, const void* /*passThroughData*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+ setSUPLVersionSync(GnssConfigSuplVersion /*version*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+enum loc_api_adapter_err LocApiBase::
+ setNMEATypesSync (uint32_t /*typesMask*/)
+DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
+
+LocationError LocApiBase::
+ setLPPConfigSync(GnssConfigLppProfileMask /*profileMask*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+
+enum loc_api_adapter_err LocApiBase::
+ setSensorPropertiesSync(bool /*gyroBiasVarianceRandomWalk_valid*/,
+ float /*gyroBiasVarianceRandomWalk*/,
+ bool /*accelBiasVarianceRandomWalk_valid*/,
+ float /*accelBiasVarianceRandomWalk*/,
+ bool /*angleBiasVarianceRandomWalk_valid*/,
+ float /*angleBiasVarianceRandomWalk*/,
+ bool /*rateBiasVarianceRandomWalk_valid*/,
+ float /*rateBiasVarianceRandomWalk*/,
+ bool /*velocityBiasVarianceRandomWalk_valid*/,
+ float /*velocityBiasVarianceRandomWalk*/)
+DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
+
+enum loc_api_adapter_err LocApiBase::
+ setSensorPerfControlConfigSync(int /*controlMode*/,
+ int /*accelSamplesPerBatch*/,
+ int /*accelBatchesPerSec*/,
+ int /*gyroSamplesPerBatch*/,
+ int /*gyroBatchesPerSec*/,
+ int /*accelSamplesPerBatchHigh*/,
+ int /*accelBatchesPerSecHigh*/,
+ int /*gyroSamplesPerBatchHigh*/,
+ int /*gyroBatchesPerSecHigh*/,
+ int /*algorithmConfig*/)
+DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)
+
+LocationError LocApiBase::
+ setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask /*aGlonassProtocol*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+LocationError LocApiBase::
+ setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask /*lppeCP*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+LocationError LocApiBase::
+ setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask /*lppeUP*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+GnssConfigSuplVersion LocApiBase::convertSuplVersion(const uint32_t /*suplVersion*/)
+DEFAULT_IMPL(GNSS_CONFIG_SUPL_VERSION_1_0_0)
+
+GnssConfigLppeControlPlaneMask LocApiBase::convertLppeCp(const uint32_t /*lppeControlPlaneMask*/)
+DEFAULT_IMPL(0)
+
+GnssConfigLppeUserPlaneMask LocApiBase::convertLppeUp(const uint32_t /*lppeUserPlaneMask*/)
+DEFAULT_IMPL(0)
+
+LocationError LocApiBase::setEmergencyExtensionWindowSync(
+ const uint32_t /*emergencyExtensionSeconds*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::setMeasurementCorrections(
+ const GnssMeasurementCorrections& /*gnssMeasurementCorrections*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ getWwanZppFix()
+DEFAULT_IMPL()
+
+void LocApiBase::
+ getBestAvailableZppFix()
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+ setGpsLockSync(GnssConfigGpsLock /*lock*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::
+ requestForAidingData(GnssAidingDataSvMask /*svDataMask*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+ setXtraVersionCheckSync(uint32_t /*check*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+LocationError LocApiBase::setBlacklistSvSync(const GnssSvIdConfig& /*config*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::setBlacklistSv(const GnssSvIdConfig& /*config*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::getBlacklistSv()
+DEFAULT_IMPL()
+
+void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::getConstellationControl()
+DEFAULT_IMPL()
+
+void LocApiBase::resetConstellationControl(LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ setConstrainedTuncMode(bool /*enabled*/,
+ float /*tuncConstraint*/,
+ uint32_t /*energyBudget*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ setPositionAssistedClockEstimatorMode(bool /*enabled*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::getGnssEnergyConsumed()
+DEFAULT_IMPL()
+
+
+void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/,
+ const GeofenceInfo& /*info*/,
+ LocApiResponseData<LocApiGeofenceData>* /*adapterResponseData*/)
+DEFAULT_IMPL()
+
+void LocApiBase::removeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::pauseGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::resumeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::modifyGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
+ const GeofenceOption& /*options*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::startTimeBasedTracking(const TrackingOptions& /*options*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::stopTimeBasedTracking(LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::startDistanceBasedTracking(uint32_t /*sessionId*/,
+ const LocationOptions& /*options*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::stopDistanceBasedTracking(uint32_t /*sessionId*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::startBatching(uint32_t /*sessionId*/, const LocationOptions& /*options*/,
+ uint32_t /*accuracy*/, uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::stopBatching(uint32_t /*sessionId*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::startOutdoorTripBatchingSync(uint32_t /*tripDistance*/,
+ uint32_t /*tripTbf*/, uint32_t /*timeout*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::startOutdoorTripBatching(uint32_t /*tripDistance*/, uint32_t /*tripTbf*/,
+ uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::reStartOutdoorTripBatching(uint32_t /*ongoingTripDistance*/,
+ uint32_t /*ongoingTripInterval*/, uint32_t /*batchingTimeout,*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::stopOutdoorTripBatchingSync(bool /*deallocBatchBuffer*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::stopOutdoorTripBatching(bool /*deallocBatchBuffer*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::getBatchedLocationsSync(size_t /*count*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::getBatchedLocations(size_t /*count*/, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::getBatchedTripLocationsSync(size_t /*count*/,
+ uint32_t /*accumulatedDistance*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::getBatchedTripLocations(size_t /*count*/, uint32_t /*accumulatedDistance*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::queryAccumulatedTripDistanceSync(uint32_t& /*accumulated_trip_distance*/,
+ uint32_t& /*numOfBatchedPositions*/)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::queryAccumulatedTripDistance(
+ LocApiResponseData<LocApiBatchData>* /*adapterResponseData*/)
+DEFAULT_IMPL()
+
+void LocApiBase::setBatchSize(size_t /*size*/)
+DEFAULT_IMPL()
+
+void LocApiBase::setTripBatchSize(size_t /*size*/)
+DEFAULT_IMPL()
+
+void LocApiBase::addToCallQueue(LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::updateSystemPowerState(PowerStateType /*powerState*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ configRobustLocation(bool /*enabled*/,
+ bool /*enableForE911*/,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ getRobustLocationConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ configMinGpsWeek(uint16_t minGpsWeek,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ getMinGpsWeek(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+LocationError LocApiBase::
+ setParameterSync(const GnssConfig& gnssConfig)
+DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)
+
+void LocApiBase::
+ getParameter(uint32_t sessionId, GnssConfigFlagsMask flags, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
+ LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+void LocApiBase::
+ getConstellationMultiBandConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
+DEFAULT_IMPL()
+
+int64_t ElapsedRealtimeEstimator::getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
+ bool isCurDataTimeTrustable, int64_t tbf) {
+ //The algorithm works follow below steps:
+ //When isCurDataTimeTrustable is meet (means Modem timestamp is already stable),
+ //1, Wait for mFixTimeStablizationThreshold fixes; While waiting for modem time
+ // stable, we set the traveltime to a default value;
+ //2, When the mFixTimeStablizationThreshold fix comes, we think now the mode time
+ // is already stable, calculate the initial AP-Modem clock diff(mCurrentClockDiff)
+ // using formula:
+ // mCurrentClockDiff = currentTimeNanos - locationTimeNanos - currentTravelTimeNanos
+ //3, since then, when the nth fix comes,
+ // 3.1 First update mCurrentClockDiff using below formula:
+ // mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
+ // - (mPrevUtcTimeNanos - mPrevBootTimeNanos)
+ // 3.2 Calculate currentTravelTimeNanos:
+ // currentTravelTimeNanos = currentTimeNanos - locationTimeNanos - mCurrentClockDiff
+ //4, It is possible that locationTimeNanos will jump,
+ // reset mFixTimeStablizationThreshold to default value, jump to step 2 to continue.
+
+ int64_t currentTravelTimeNanos = mInitialTravelTime;
+ struct timespec currentTime;
+ int64_t sinceBootTimeNanos;
+ if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
+ if (isCurDataTimeTrustable) {
+ if (tbf > 0 && tbf != curDataTimeNanos - mPrevDataTimeNanos) {
+ mFixTimeStablizationThreshold = 5;
+ }
+ int64_t currentTimeNanos = (int64_t)currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
+ LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
+ " locationTimeNanos:%" PRIi64 "",
+ sinceBootTimeNanos, currentTimeNanos, curDataTimeNanos);
+ if (mFixTimeStablizationThreshold == 0) {
+ currentTravelTimeNanos = mInitialTravelTime;
+ mCurrentClockDiff = currentTimeNanos - curDataTimeNanos - currentTravelTimeNanos;
+ } else if (mFixTimeStablizationThreshold < 0) {
+ mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
+ - (mPrevUtcTimeNanos - mPrevBootTimeNanos);
+ currentTravelTimeNanos = currentTimeNanos - curDataTimeNanos - mCurrentClockDiff;
+ }
+
+ mPrevUtcTimeNanos = currentTimeNanos;
+ mPrevBootTimeNanos = sinceBootTimeNanos;
+ mPrevDataTimeNanos = curDataTimeNanos;
+ mFixTimeStablizationThreshold--;
+ }
+ } else {
+ return -1;
+ }
+ LOC_LOGd("Estimated travel time: %" PRIi64 "", currentTravelTimeNanos);
+ return (sinceBootTimeNanos - currentTravelTimeNanos);
+}
+
+void ElapsedRealtimeEstimator::reset() {
+ mCurrentClockDiff = 0;
+ mPrevDataTimeNanos = 0;
+ mPrevUtcTimeNanos = 0;
+ mPrevBootTimeNanos = 0;
+ mFixTimeStablizationThreshold = 5;
+}
+
+int64_t ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin) {
+ struct timespec currentTime;
+ int64_t sinceBootTimeNanos;
+ int64_t elapsedRealTimeNanos;
+
+ if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
+ uint64_t qtimerDiff = 0;
+ uint64_t qTimerTickCount = getQTimerTickCount();
+ if (qTimerTickCount >= qtimerTicksAtOrigin) {
+ qtimerDiff = qTimerTickCount - qtimerTicksAtOrigin;
+ }
+ LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " qtimerTicksAtOrigin=%" PRIi64 ""
+ " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "",
+ sinceBootTimeNanos, qtimerTicksAtOrigin, qTimerTickCount, qtimerDiff);
+ uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff));
+
+ /* If the time difference between Qtimer on modem side and Qtimer on AP side
+ is greater than one second we assume this is a dual-SoC device such as
+ Kona and will try to get Qtimer on modem side and on AP side and
+ will adjust our difference accordingly */
+ if (qTimerDiffNanos > 1000000000) {
+ uint64_t qtimerDelta = getQTimerDeltaNanos();
+ if (qTimerDiffNanos >= qtimerDelta) {
+ qTimerDiffNanos -= qtimerDelta;
+ }
+ }
+
+ LOC_LOGd("Qtimer travel time: %" PRIi64 "", qTimerDiffNanos);
+ if (sinceBootTimeNanos >= qTimerDiffNanos) {
+ elapsedRealTimeNanos = sinceBootTimeNanos - qTimerDiffNanos;
+ } else {
+ elapsedRealTimeNanos = -1;
+ }
+ } else {
+ elapsedRealTimeNanos = -1;
+ }
+ return elapsedRealTimeNanos;
+}
+
+bool ElapsedRealtimeEstimator::getCurrentTime(
+ struct timespec& currentTime, int64_t& sinceBootTimeNanos)
+{
+ struct timespec sinceBootTime;
+ struct timespec sinceBootTimeTest;
+ bool clockGetTimeSuccess = false;
+ const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000;
+ const uint32_t MAX_GET_TIME_COUNT = 20;
+ /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
+ or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
+ for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
+ if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
+ break;
+ };
+ if (clock_gettime(CLOCK_REALTIME, &currentTime) != 0) {
+ break;
+ }
+ if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
+ break;
+ };
+ sinceBootTimeNanos = (int64_t)sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
+ int64_t sinceBootTimeTestNanos =
+ (int64_t)sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
+ int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;
+
+ /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
+ interruption or context switch between clock_gettime for CLOCK_BOOTIME and
+ clock_gettime for CLOCK_REALTIME */
+ if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
+ clockGetTimeSuccess = true;
+ break;
+ } else {
+ LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
+ sinceBootTimeDeltaNanos, i + 1);
+ }
+ }
+ return clockGetTimeSuccess;
+}
+} // namespace loc_core
diff --git a/gps/core/LocApiBase.h b/gps/core/LocApiBase.h
new file mode 100644
index 0000000..121f795
--- /dev/null
+++ b/gps/core/LocApiBase.h
@@ -0,0 +1,375 @@
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef LOC_API_BASE_H
+#define LOC_API_BASE_H
+
+#include <stddef.h>
+#include <ctype.h>
+#include <gps_extended.h>
+#include <LocationAPI.h>
+#include <MsgTask.h>
+#include <LocSharedLock.h>
+#include <log_util.h>
+#ifdef NO_UNORDERED_SET_OR_MAP
+ #include <map>
+#else
+ #include <unordered_map>
+#endif
+#include <inttypes.h>
+#include <functional>
+
+using namespace loc_util;
+
+namespace loc_core {
+
+class ContextBase;
+struct LocApiResponse;
+template <typename> struct LocApiResponseData;
+
+int hexcode(char *hexstring, int string_size,
+ const char *data, int data_size);
+int decodeAddress(char *addr_string, int string_size,
+ const char *data, int data_size);
+
+#define MAX_ADAPTERS 10
+#define MAX_FEATURE_LENGTH 100
+
+#define TO_ALL_ADAPTERS(adapters, call) \
+ for (int i = 0; i < MAX_ADAPTERS && NULL != (adapters)[i]; i++) { \
+ call; \
+ }
+
+#define TO_1ST_HANDLING_ADAPTER(adapters, call) \
+ for (int i = 0; i <MAX_ADAPTERS && NULL != (adapters)[i] && !(call); i++);
+
+class LocAdapterBase;
+struct LocSsrMsg;
+struct LocOpenMsg;
+
+typedef struct
+{
+ uint32_t accumulatedDistance;
+ uint32_t numOfBatchedPositions;
+} LocApiBatchData;
+
+typedef struct
+{
+ uint32_t hwId;
+} LocApiGeofenceData;
+
+struct LocApiMsg: LocMsg {
+ private:
+ std::function<void ()> mProcImpl;
+ inline virtual void proc() const {
+ mProcImpl();
+ }
+ public:
+ inline LocApiMsg(std::function<void ()> procImpl ) :
+ mProcImpl(procImpl) {}
+};
+
+class LocApiProxyBase {
+public:
+ inline LocApiProxyBase() {}
+ inline virtual ~LocApiProxyBase() {}
+ inline virtual void* getSibling2() { return NULL; }
+ inline virtual double getGloRfLoss(uint32_t left,
+ uint32_t center, uint32_t right, uint8_t gloFrequency) { return 0.0; }
+};
+
+class LocApiBase {
+ friend struct LocSsrMsg;
+ //LocOpenMsg calls open() which makes it necessary to declare
+ //it as a friend
+ friend struct LocOpenMsg;
+ friend struct LocCloseMsg;
+ friend struct LocKillMsg;
+ friend class ContextBase;
+ static MsgTask* mMsgTask;
+ static volatile int32_t mMsgTaskRefCount;
+ LocAdapterBase* mLocAdapters[MAX_ADAPTERS];
+
+protected:
+ ContextBase *mContext;
+ virtual enum loc_api_adapter_err
+ open(LOC_API_ADAPTER_EVENT_MASK_T mask);
+ virtual enum loc_api_adapter_err
+ close();
+ LOC_API_ADAPTER_EVENT_MASK_T getEvtMask();
+ LOC_API_ADAPTER_EVENT_MASK_T mMask;
+ uint32_t mNmeaMask;
+ LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask,
+ ContextBase* context = NULL);
+ inline virtual ~LocApiBase() {
+ android_atomic_dec(&mMsgTaskRefCount);
+ if (nullptr != mMsgTask && 0 == mMsgTaskRefCount) {
+ delete mMsgTask;
+ mMsgTask = nullptr;
+ }
+ }
+ bool isInSession();
+ const LOC_API_ADAPTER_EVENT_MASK_T mExcludedMask;
+ bool isMaster();
+
+public:
+ inline void sendMsg(const LocMsg* msg) const {
+ if (nullptr != mMsgTask) {
+ mMsgTask->sendMsg(msg);
+ }
+ }
+ inline void destroy() {
+ close();
+ struct LocKillMsg : public LocMsg {
+ LocApiBase* mLocApi;
+ inline LocKillMsg(LocApiBase* locApi) : LocMsg(), mLocApi(locApi) {}
+ inline virtual void proc() const {
+ delete mLocApi;
+ }
+ };
+ sendMsg(new LocKillMsg(this));
+ }
+
+ static bool needReport(const UlpLocation& ulpLocation,
+ enum loc_sess_status status,
+ LocPosTechMask techMask);
+
+ void addAdapter(LocAdapterBase* adapter);
+ void removeAdapter(LocAdapterBase* adapter);
+
+ // upward calls
+ void handleEngineUpEvent();
+ void handleEngineDownEvent();
+ void reportPosition(UlpLocation& location,
+ GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask =
+ LOC_POS_TECH_MASK_DEFAULT,
+ GnssDataNotification* pDataNotify = nullptr,
+ int msInWeek = -1);
+ void reportSv(GnssSvNotification& svNotify);
+ void reportSvPolynomial(GnssSvPolynomial &svPolynomial);
+ void reportSvEphemeris(GnssSvEphemerisReport &svEphemeris);
+ void reportStatus(LocGpsStatusValue status);
+ void reportNmea(const char* nmea, int length);
+ void reportData(GnssDataNotification& dataNotify, int msInWeek);
+ void reportXtraServer(const char* url1, const char* url2,
+ const char* url3, const int maxlength);
+ void reportLocationSystemInfo(const LocationSystemInfo& locationSystemInfo);
+ void requestXtraData();
+ void requestTime();
+ void requestLocation();
+ void requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask);
+ void releaseATL(int connHandle);
+ void requestNiNotify(GnssNiNotification &notify, const void* data,
+ const LocInEmergency emergencyState);
+ void reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek);
+ void reportWwanZppFix(LocGpsLocation &zppLoc);
+ void reportZppBestAvailableFix(LocGpsLocation &zppLoc, GpsLocationExtended &location_extended,
+ LocPosTechMask tech_mask);
+ void reportGnssSvIdConfig(const GnssSvIdConfig& config);
+ void reportGnssSvTypeConfig(const GnssSvTypeConfig& config);
+ void requestOdcpi(OdcpiRequestInfo& request);
+ void reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
+ void reportDeleteAidingDataEvent(GnssAidingData& aidingData);
+ void reportKlobucharIonoModel(GnssKlobucharIonoModel& ionoModel);
+ void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo);
+ void sendNfwNotification(GnssNfwNotification& notification);
+ void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig);
+ void reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo);
+ void reportQwesCapabilities
+ (
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+ );
+
+ void geofenceBreach(size_t count, uint32_t* hwIds, Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp);
+ void geofenceStatus(GeofenceStatusAvailable available);
+ void reportDBTPosition(UlpLocation &location,
+ GpsLocationExtended &locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask loc_technology_mask);
+ void reportLocations(Location* locations, size_t count, BatchingMode batchingMode);
+ void reportCompletedTrips(uint32_t accumulated_distance);
+ void handleBatchStatusEvent(BatchingStatus batchStatus);
+
+ // downward calls
+ virtual void* getSibling();
+ virtual LocApiProxyBase* getLocApiProxy();
+ virtual void startFix(const LocPosMode& fixCriteria, LocApiResponse* adapterResponse);
+ virtual void stopFix(LocApiResponse* adapterResponse);
+ virtual void deleteAidingData(const GnssAidingData& data, LocApiResponse* adapterResponse);
+ virtual void injectPosition(double latitude, double longitude, float accuracy,
+ bool onDemandCpi);
+ virtual void injectPosition(const GnssLocationInfoNotification &locationInfo,
+ bool onDemandCpi=false);
+ virtual void injectPosition(const Location& location, bool onDemandCpi);
+ virtual void setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty);
+ virtual void atlOpenStatus(int handle, int is_succ, char* apn, uint32_t apnLen,
+ AGpsBearerType bear, LocAGpsType agpsType, LocApnTypeMask mask);
+ virtual void atlCloseStatus(int handle, int is_succ);
+ virtual LocationError setServerSync(const char* url, int len, LocServerType type);
+ virtual LocationError setServerSync(unsigned int ip, int port, LocServerType type);
+ virtual void informNiResponse(GnssNiResponse userResponse, const void* passThroughData);
+ virtual LocationError setSUPLVersionSync(GnssConfigSuplVersion version);
+ virtual enum loc_api_adapter_err setNMEATypesSync(uint32_t typesMask);
+ virtual LocationError setLPPConfigSync(GnssConfigLppProfileMask profileMask);
+ virtual enum loc_api_adapter_err setSensorPropertiesSync(
+ bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk,
+ bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk,
+ bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk,
+ bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk,
+ bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk);
+ virtual enum loc_api_adapter_err setSensorPerfControlConfigSync(int controlMode,
+ int accelSamplesPerBatch, int accelBatchesPerSec, int gyroSamplesPerBatch,
+ int gyroBatchesPerSec, int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh,
+ int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, int algorithmConfig);
+ virtual LocationError
+ setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol);
+ virtual LocationError setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP);
+ virtual LocationError setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP);
+ virtual GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion);
+ virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask);
+ virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask);
+ virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds);
+ virtual void setMeasurementCorrections(
+ const GnssMeasurementCorrections& gnssMeasurementCorrections);
+
+ virtual void getWwanZppFix();
+ virtual void getBestAvailableZppFix();
+ virtual LocationError setGpsLockSync(GnssConfigGpsLock lock);
+ virtual void requestForAidingData(GnssAidingDataSvMask svDataMask);
+ virtual LocationError setXtraVersionCheckSync(uint32_t check);
+ /* Requests for SV/Constellation Control */
+ virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config);
+ virtual void setBlacklistSv(const GnssSvIdConfig& config,
+ LocApiResponse *adapterResponse=nullptr);
+ virtual void getBlacklistSv();
+ virtual void setConstellationControl(const GnssSvTypeConfig& config,
+ LocApiResponse *adapterResponse=nullptr);
+ virtual void getConstellationControl();
+ virtual void resetConstellationControl(LocApiResponse *adapterResponse=nullptr);
+
+ virtual void setConstrainedTuncMode(bool enabled,
+ float tuncConstraint,
+ uint32_t energyBudget,
+ LocApiResponse* adapterResponse=nullptr);
+ virtual void setPositionAssistedClockEstimatorMode(bool enabled,
+ LocApiResponse* adapterResponse=nullptr);
+ virtual void getGnssEnergyConsumed();
+
+ virtual void addGeofence(uint32_t clientId, const GeofenceOption& options,
+ const GeofenceInfo& info, LocApiResponseData<LocApiGeofenceData>* adapterResponseData);
+ virtual void removeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
+ virtual void pauseGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
+ virtual void resumeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
+ virtual void modifyGeofence(uint32_t hwId, uint32_t clientId, const GeofenceOption& options,
+ LocApiResponse* adapterResponse);
+
+ virtual void startTimeBasedTracking(const TrackingOptions& options,
+ LocApiResponse* adapterResponse);
+ virtual void stopTimeBasedTracking(LocApiResponse* adapterResponse);
+ virtual void startDistanceBasedTracking(uint32_t sessionId, const LocationOptions& options,
+ LocApiResponse* adapterResponse);
+ virtual void stopDistanceBasedTracking(uint32_t sessionId,
+ LocApiResponse* adapterResponse = nullptr);
+ virtual void startBatching(uint32_t sessionId, const LocationOptions& options,
+ uint32_t accuracy, uint32_t timeout, LocApiResponse* adapterResponse);
+ virtual void stopBatching(uint32_t sessionId, LocApiResponse* adapterResponse);
+ virtual LocationError startOutdoorTripBatchingSync(uint32_t tripDistance,
+ uint32_t tripTbf, uint32_t timeout);
+ virtual void startOutdoorTripBatching(uint32_t tripDistance,
+ uint32_t tripTbf, uint32_t timeout, LocApiResponse* adapterResponse);
+ virtual void reStartOutdoorTripBatching(uint32_t ongoingTripDistance,
+ uint32_t ongoingTripInterval, uint32_t batchingTimeout,
+ LocApiResponse* adapterResponse);
+ virtual LocationError stopOutdoorTripBatchingSync(bool deallocBatchBuffer = true);
+ virtual void stopOutdoorTripBatching(bool deallocBatchBuffer = true,
+ LocApiResponse* adapterResponse = nullptr);
+ virtual LocationError getBatchedLocationsSync(size_t count);
+ virtual void getBatchedLocations(size_t count, LocApiResponse* adapterResponse);
+ virtual LocationError getBatchedTripLocationsSync(size_t count, uint32_t accumulatedDistance);
+ virtual void getBatchedTripLocations(size_t count, uint32_t accumulatedDistance,
+ LocApiResponse* adapterResponse);
+ virtual LocationError queryAccumulatedTripDistanceSync(uint32_t &accumulated_trip_distance,
+ uint32_t &numOfBatchedPositions);
+ virtual void queryAccumulatedTripDistance(
+ LocApiResponseData<LocApiBatchData>* adapterResponseData);
+ virtual void setBatchSize(size_t size);
+ virtual void setTripBatchSize(size_t size);
+ virtual void addToCallQueue(LocApiResponse* adapterResponse);
+
+ void updateEvtMask();
+ void updateNmeaMask(uint32_t mask);
+
+ virtual void updateSystemPowerState(PowerStateType systemPowerState);
+
+ virtual void configRobustLocation(bool enable, bool enableForE911,
+ LocApiResponse* adapterResponse=nullptr);
+ virtual void getRobustLocationConfig(uint32_t sessionId, LocApiResponse* adapterResponse);
+ virtual void configMinGpsWeek(uint16_t minGpsWeek,
+ LocApiResponse* adapterResponse=nullptr);
+ virtual void getMinGpsWeek(uint32_t sessionId, LocApiResponse* adapterResponse);
+
+ virtual LocationError setParameterSync(const GnssConfig & gnssConfig);
+ virtual void getParameter(uint32_t sessionId, GnssConfigFlagsMask flags,
+ LocApiResponse* adapterResponse=nullptr);
+
+ virtual void configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
+ LocApiResponse* adapterResponse=nullptr);
+ virtual void getConstellationMultiBandConfig(uint32_t sessionId,
+ LocApiResponse* adapterResponse=nullptr);
+};
+
+class ElapsedRealtimeEstimator {
+private:
+ int64_t mCurrentClockDiff;
+ int64_t mPrevUtcTimeNanos;
+ int64_t mPrevBootTimeNanos;
+ int64_t mFixTimeStablizationThreshold;
+ int64_t mInitialTravelTime;
+ int64_t mPrevDataTimeNanos;
+public:
+
+ ElapsedRealtimeEstimator(int64_t travelTimeNanosEstimate):
+ mInitialTravelTime(travelTimeNanosEstimate) {reset();}
+ int64_t getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
+ bool isCurDataTimeTrustable, int64_t tbf);
+ inline int64_t getElapsedRealtimeUncNanos() { return 5000000;}
+ void reset();
+
+ static int64_t getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin);
+ static bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos);
+};
+
+typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask,
+ ContextBase *context);
+
+} // namespace loc_core
+
+#endif //LOC_API_BASE_H
diff --git a/gps/core/LocContext.cpp b/gps/core/LocContext.cpp
new file mode 100644
index 0000000..272c08c
--- /dev/null
+++ b/gps/core/LocContext.cpp
@@ -0,0 +1,87 @@
+/* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_Ctx"
+
+#include <cutils/sched_policy.h>
+#include <unistd.h>
+#include <LocContext.h>
+#include <msg_q.h>
+#include <log_util.h>
+#include <loc_log.h>
+
+namespace loc_core {
+
+const MsgTask* LocContext::mMsgTask = NULL;
+ContextBase* LocContext::mContext = NULL;
+// the name must be shorter than 15 chars
+const char* LocContext::mLocationHalName = "Loc_hal_worker";
+#ifndef USE_GLIB
+const char* LocContext::mLBSLibName = "liblbs_core.so";
+#else
+const char* LocContext::mLBSLibName = "liblbs_core.so.1";
+#endif
+
+pthread_mutex_t LocContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER;
+
+const MsgTask* LocContext::getMsgTask(const char* name)
+{
+ if (NULL == mMsgTask) {
+ mMsgTask = new MsgTask(name);
+ }
+ return mMsgTask;
+}
+
+ContextBase* LocContext::getLocContext(const char* name)
+{
+ pthread_mutex_lock(&LocContext::mGetLocContextMutex);
+ LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__);
+ if (NULL == mContext) {
+ LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__);
+ const MsgTask* msgTask = getMsgTask(name);
+ mContext = new LocContext(msgTask);
+ }
+ pthread_mutex_unlock(&LocContext::mGetLocContextMutex);
+
+ return mContext;
+}
+
+void LocContext :: injectFeatureConfig(ContextBase *curContext)
+{
+ LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config",
+ __func__, __LINE__, ((LocContext *)curContext)->mLBSProxy);
+ ((LocContext *)curContext)->mLBSProxy->injectFeatureConfig(curContext);
+}
+
+LocContext::LocContext(const MsgTask* msgTask) :
+ ContextBase(msgTask, 0, mLBSLibName)
+{
+}
+
+}
diff --git a/gps/core/LocContext.h b/gps/core/LocContext.h
new file mode 100644
index 0000000..628ed93
--- /dev/null
+++ b/gps/core/LocContext.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2011-2014, 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_CONTEXT__
+#define __LOC_CONTEXT__
+
+#include <stdbool.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <ContextBase.h>
+
+namespace loc_core {
+
+class LocContext : public ContextBase {
+ static const MsgTask* mMsgTask;
+ static ContextBase* mContext;
+ static const MsgTask* getMsgTask(const char* name);
+ static pthread_mutex_t mGetLocContextMutex;
+
+protected:
+ LocContext(const MsgTask* msgTask);
+ inline virtual ~LocContext() {}
+
+public:
+ static const char* mLBSLibName;
+ static const char* mLocationHalName;
+
+ static ContextBase* getLocContext(const char* name);
+
+ static void injectFeatureConfig(ContextBase *context);
+};
+
+}
+
+#endif //__LOC_CONTEXT__
diff --git a/gps/core/Makefile.am b/gps/core/Makefile.am
new file mode 100644
index 0000000..291dbb5
--- /dev/null
+++ b/gps/core/Makefile.am
@@ -0,0 +1,74 @@
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS = -I./ \
+ $(LOCPLA_CFLAGS) \
+ $(GPSUTILS_CFLAGS) \
+ -I./data-items/ \
+ -I./data-items/common \
+ -I./observer \
+ -I$(WORKSPACE)/gps-noship/flp \
+ -D__func__=__PRETTY_FUNCTION__ \
+ -fno-short-enums \
+ -std=c++11
+
+libloc_core_la_h_sources = \
+ LocApiBase.h \
+ LocAdapterBase.h \
+ ContextBase.h \
+ LocContext.h \
+ LBSProxyBase.h \
+ loc_core_log.h \
+ LocAdapterProxyBase.h \
+ EngineHubProxyBase.h \
+ data-items/DataItemId.h \
+ data-items/IDataItemCore.h \
+ data-items/DataItemConcreteTypesBase.h \
+ observer/IDataItemObserver.h \
+ observer/IDataItemSubscription.h \
+ observer/IFrameworkActionReq.h \
+ observer/IOsObserver.h \
+ SystemStatusOsObserver.h \
+ SystemStatus.h
+
+libloc_core_la_c_sources = \
+ LocApiBase.cpp \
+ LocAdapterBase.cpp \
+ ContextBase.cpp \
+ LocContext.cpp \
+ loc_core_log.cpp \
+ data-items/DataItemsFactoryProxy.cpp \
+ SystemStatusOsObserver.cpp \
+ SystemStatus.cpp
+
+if USE_EXTERNAL_AP
+AM_CFLAGS += -DFEATURE_EXTERNAL_AP
+endif
+
+library_includedir = $(pkgincludedir)
+
+library_include_HEADERS = $(libloc_core_la_h_sources)
+
+libloc_core_la_SOURCES = $(libloc_core_la_c_sources)
+
+if USE_GLIB
+libloc_core_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
+libloc_core_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
+libloc_core_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
+else
+libloc_core_la_CFLAGS = $(AM_CFLAGS)
+libloc_core_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
+libloc_core_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+if USE_FEATURE_AUTOMOTIVE
+AM_CFLAGS += -DFEATURE_AUTOMOTIVE
+endif
+
+libloc_core_la_LIBADD = -ldl $(GPSUTILS_LIBS)
+
+#Create and Install libraries
+lib_LTLIBRARIES = libloc_core.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = loc-core.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/gps/core/SystemStatus.cpp b/gps/core/SystemStatus.cpp
new file mode 100644
index 0000000..d792577
--- /dev/null
+++ b/gps/core/SystemStatus.cpp
@@ -0,0 +1,1760 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_SystemStatus"
+
+#include <inttypes.h>
+#include <string>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <loc_pla.h>
+#include <log_util.h>
+#include <loc_nmea.h>
+#include <DataItemsFactoryProxy.h>
+#include <SystemStatus.h>
+#include <SystemStatusOsObserver.h>
+#include <DataItemConcreteTypesBase.h>
+
+namespace loc_core
+{
+
+/******************************************************************************
+ SystemStatusNmeaBase - base class for all NMEA parsers
+******************************************************************************/
+class SystemStatusNmeaBase
+{
+protected:
+ std::vector<std::string> mField;
+
+ SystemStatusNmeaBase(const char *str_in, uint32_t len_in)
+ {
+ // check size and talker
+ if (!loc_nmea_is_debug(str_in, len_in)) {
+ return;
+ }
+
+ std::string parser(str_in);
+ std::string::size_type index = 0;
+
+ // verify checksum field
+ index = parser.find("*");
+ if (index == std::string::npos) {
+ return;
+ }
+ parser[index] = ',';
+
+ // tokenize parser
+ while (1) {
+ std::string str;
+ index = parser.find(",");
+ if (index == std::string::npos) {
+ break;
+ }
+ str = parser.substr(0, index);
+ parser = parser.substr(index + 1);
+ mField.push_back(str);
+ }
+ }
+
+ virtual ~SystemStatusNmeaBase() { }
+
+public:
+ static const uint32_t NMEA_MINSIZE = DEBUG_NMEA_MINSIZE;
+ static const uint32_t NMEA_MAXSIZE = DEBUG_NMEA_MAXSIZE;
+};
+
+/******************************************************************************
+ SystemStatusPQWM1
+******************************************************************************/
+class SystemStatusPQWM1
+{
+public:
+ uint16_t mGpsWeek; // x1
+ uint32_t mGpsTowMs; // x2
+ uint8_t mTimeValid; // x3
+ uint8_t mTimeSource; // x4
+ int32_t mTimeUnc; // x5
+ int32_t mClockFreqBias; // x6
+ int32_t mClockFreqBiasUnc; // x7
+ uint8_t mXoState; // x8
+ int32_t mPgaGain; // x9
+ uint32_t mGpsBpAmpI; // xA
+ uint32_t mGpsBpAmpQ; // xB
+ uint32_t mAdcI; // xC
+ uint32_t mAdcQ; // xD
+ uint32_t mJammerGps; // xE
+ uint32_t mJammerGlo; // xF
+ uint32_t mJammerBds; // x10
+ uint32_t mJammerGal; // x11
+ uint32_t mRecErrorRecovery; // x12
+ double mAgcGps; // x13
+ double mAgcGlo; // x14
+ double mAgcBds; // x15
+ double mAgcGal; // x16
+ int32_t mLeapSeconds;// x17
+ int32_t mLeapSecUnc; // x18
+ uint32_t mGloBpAmpI; // x19
+ uint32_t mGloBpAmpQ; // x1A
+ uint32_t mBdsBpAmpI; // x1B
+ uint32_t mBdsBpAmpQ; // x1C
+ uint32_t mGalBpAmpI; // x1D
+ uint32_t mGalBpAmpQ; // x1E
+ uint64_t mTimeUncNs; // x1F
+};
+
+// parser
+class SystemStatusPQWM1parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eGpsWeek = 1,
+ eGpsTowMs = 2,
+ eTimeValid = 3,
+ eTimeSource = 4,
+ eTimeUnc = 5,
+ eClockFreqBias = 6,
+ eClockFreqBiasUnc = 7,
+ eXoState = 8,
+ ePgaGain = 9,
+ eGpsBpAmpI = 10,
+ eGpsBpAmpQ = 11,
+ eAdcI = 12,
+ eAdcQ = 13,
+ eJammerGps = 14,
+ eJammerGlo = 15,
+ eJammerBds = 16,
+ eJammerGal = 17,
+ eRecErrorRecovery = 18,
+ eAgcGps = 19,
+ eAgcGlo = 20,
+ eAgcBds = 21,
+ eAgcGal = 22,
+ eMax0 = eAgcGal,
+ eLeapSeconds = 23,
+ eLeapSecUnc = 24,
+ eGloBpAmpI = 25,
+ eGloBpAmpQ = 26,
+ eBdsBpAmpI = 27,
+ eBdsBpAmpQ = 28,
+ eGalBpAmpI = 29,
+ eGalBpAmpQ = 30,
+ eTimeUncNs = 31,
+ eMax
+ };
+ SystemStatusPQWM1 mM1;
+
+public:
+ inline uint16_t getGpsWeek() { return mM1.mGpsWeek; }
+ inline uint32_t getGpsTowMs() { return mM1.mGpsTowMs; }
+ inline uint8_t getTimeValid() { return mM1.mTimeValid; }
+ inline uint8_t getTimeSource() { return mM1.mTimeSource; }
+ inline int32_t getTimeUnc() { return mM1.mTimeUnc; }
+ inline int32_t getClockFreqBias() { return mM1.mClockFreqBias; }
+ inline int32_t getClockFreqBiasUnc() { return mM1.mClockFreqBiasUnc; }
+ inline uint8_t getXoState() { return mM1.mXoState;}
+ inline int32_t getPgaGain() { return mM1.mPgaGain; }
+ inline uint32_t getGpsBpAmpI() { return mM1.mGpsBpAmpI; }
+ inline uint32_t getGpsBpAmpQ() { return mM1.mGpsBpAmpQ; }
+ inline uint32_t getAdcI() { return mM1.mAdcI; }
+ inline uint32_t getAdcQ() { return mM1.mAdcQ; }
+ inline uint32_t getJammerGps() { return mM1.mJammerGps; }
+ inline uint32_t getJammerGlo() { return mM1.mJammerGlo; }
+ inline uint32_t getJammerBds() { return mM1.mJammerBds; }
+ inline uint32_t getJammerGal() { return mM1.mJammerGal; }
+ inline uint32_t getAgcGps() { return mM1.mAgcGps; }
+ inline uint32_t getAgcGlo() { return mM1.mAgcGlo; }
+ inline uint32_t getAgcBds() { return mM1.mAgcBds; }
+ inline uint32_t getAgcGal() { return mM1.mAgcGal; }
+ inline uint32_t getRecErrorRecovery() { return mM1.mRecErrorRecovery; }
+ inline int32_t getLeapSeconds(){ return mM1.mLeapSeconds; }
+ inline int32_t getLeapSecUnc() { return mM1.mLeapSecUnc; }
+ inline uint32_t getGloBpAmpI() { return mM1.mGloBpAmpI; }
+ inline uint32_t getGloBpAmpQ() { return mM1.mGloBpAmpQ; }
+ inline uint32_t getBdsBpAmpI() { return mM1.mBdsBpAmpI; }
+ inline uint32_t getBdsBpAmpQ() { return mM1.mBdsBpAmpQ; }
+ inline uint32_t getGalBpAmpI() { return mM1.mGalBpAmpI; }
+ inline uint32_t getGalBpAmpQ() { return mM1.mGalBpAmpQ; }
+ inline uint64_t getTimeUncNs() { return mM1.mTimeUncNs; }
+
+ SystemStatusPQWM1parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ memset(&mM1, 0, sizeof(mM1));
+ if (mField.size() <= eMax0) {
+ LOC_LOGE("PQWM1parser - invalid size=%zu", mField.size());
+ mM1.mTimeValid = 0;
+ return;
+ }
+ mM1.mGpsWeek = atoi(mField[eGpsWeek].c_str());
+ mM1.mGpsTowMs = atoi(mField[eGpsTowMs].c_str());
+ mM1.mTimeValid = atoi(mField[eTimeValid].c_str());
+ mM1.mTimeSource = atoi(mField[eTimeSource].c_str());
+ mM1.mTimeUnc = atoi(mField[eTimeUnc].c_str());
+ mM1.mClockFreqBias = atoi(mField[eClockFreqBias].c_str());
+ mM1.mClockFreqBiasUnc = atoi(mField[eClockFreqBiasUnc].c_str());
+ mM1.mXoState = atoi(mField[eXoState].c_str());
+ mM1.mPgaGain = atoi(mField[ePgaGain].c_str());
+ mM1.mGpsBpAmpI = atoi(mField[eGpsBpAmpI].c_str());
+ mM1.mGpsBpAmpQ = atoi(mField[eGpsBpAmpQ].c_str());
+ mM1.mAdcI = atoi(mField[eAdcI].c_str());
+ mM1.mAdcQ = atoi(mField[eAdcQ].c_str());
+ mM1.mJammerGps = atoi(mField[eJammerGps].c_str());
+ mM1.mJammerGlo = atoi(mField[eJammerGlo].c_str());
+ mM1.mJammerBds = atoi(mField[eJammerBds].c_str());
+ mM1.mJammerGal = atoi(mField[eJammerGal].c_str());
+ mM1.mRecErrorRecovery = atoi(mField[eRecErrorRecovery].c_str());
+ mM1.mAgcGps = atof(mField[eAgcGps].c_str());
+ mM1.mAgcGlo = atof(mField[eAgcGlo].c_str());
+ mM1.mAgcBds = atof(mField[eAgcBds].c_str());
+ mM1.mAgcGal = atof(mField[eAgcGal].c_str());
+ if (mField.size() > eLeapSecUnc) {
+ mM1.mLeapSeconds = atoi(mField[eLeapSeconds].c_str());
+ mM1.mLeapSecUnc = atoi(mField[eLeapSecUnc].c_str());
+ }
+ if (mField.size() > eGalBpAmpQ) {
+ mM1.mGloBpAmpI = atoi(mField[eGloBpAmpI].c_str());
+ mM1.mGloBpAmpQ = atoi(mField[eGloBpAmpQ].c_str());
+ mM1.mBdsBpAmpI = atoi(mField[eBdsBpAmpI].c_str());
+ mM1.mBdsBpAmpQ = atoi(mField[eBdsBpAmpQ].c_str());
+ mM1.mGalBpAmpI = atoi(mField[eGalBpAmpI].c_str());
+ mM1.mGalBpAmpQ = atoi(mField[eGalBpAmpQ].c_str());
+ }
+ if (mField.size() > eTimeUncNs) {
+ mM1.mTimeUncNs = strtoull(mField[eTimeUncNs].c_str(), nullptr, 10);
+ }
+ }
+
+ inline SystemStatusPQWM1& get() { return mM1;} //getparser
+};
+
+/******************************************************************************
+ SystemStatusPQWP1
+******************************************************************************/
+class SystemStatusPQWP1
+{
+public:
+ uint8_t mEpiValidity; // x4
+ float mEpiLat; // x5
+ float mEpiLon; // x6
+ float mEpiAlt; // x7
+ float mEpiHepe; // x8
+ float mEpiAltUnc; // x9
+ uint8_t mEpiSrc; // x10
+};
+
+class SystemStatusPQWP1parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eEpiValidity = 2,
+ eEpiLat = 3,
+ eEpiLon = 4,
+ eEpiAlt = 5,
+ eEpiHepe = 6,
+ eEpiAltUnc = 7,
+ eEpiSrc = 8,
+ eMax
+ };
+ SystemStatusPQWP1 mP1;
+
+public:
+ inline uint8_t getEpiValidity() { return mP1.mEpiValidity; }
+ inline float getEpiLat() { return mP1.mEpiLat; }
+ inline float getEpiLon() { return mP1.mEpiLon; }
+ inline float getEpiAlt() { return mP1.mEpiAlt; }
+ inline float getEpiHepe() { return mP1.mEpiHepe; }
+ inline float getEpiAltUnc() { return mP1.mEpiAltUnc; }
+ inline uint8_t getEpiSrc() { return mP1.mEpiSrc; }
+
+ SystemStatusPQWP1parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP1, 0, sizeof(mP1));
+ mP1.mEpiValidity = strtol(mField[eEpiValidity].c_str(), NULL, 16);
+ mP1.mEpiLat = atof(mField[eEpiLat].c_str());
+ mP1.mEpiLon = atof(mField[eEpiLon].c_str());
+ mP1.mEpiAlt = atof(mField[eEpiAlt].c_str());
+ mP1.mEpiHepe = atoi(mField[eEpiHepe].c_str());
+ mP1.mEpiAltUnc = atof(mField[eEpiAltUnc].c_str());
+ mP1.mEpiSrc = atoi(mField[eEpiSrc].c_str());
+ }
+
+ inline SystemStatusPQWP1& get() { return mP1;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP2
+******************************************************************************/
+class SystemStatusPQWP2
+{
+public:
+ float mBestLat; // x4
+ float mBestLon; // x5
+ float mBestAlt; // x6
+ float mBestHepe; // x7
+ float mBestAltUnc; // x8
+};
+
+class SystemStatusPQWP2parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eBestLat = 2,
+ eBestLon = 3,
+ eBestAlt = 4,
+ eBestHepe = 5,
+ eBestAltUnc = 6,
+ eMax
+ };
+ SystemStatusPQWP2 mP2;
+
+public:
+ inline float getBestLat() { return mP2.mBestLat; }
+ inline float getBestLon() { return mP2.mBestLon; }
+ inline float getBestAlt() { return mP2.mBestAlt; }
+ inline float getBestHepe() { return mP2.mBestHepe; }
+ inline float getBestAltUnc() { return mP2.mBestAltUnc; }
+
+ SystemStatusPQWP2parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP2, 0, sizeof(mP2));
+ mP2.mBestLat = atof(mField[eBestLat].c_str());
+ mP2.mBestLon = atof(mField[eBestLon].c_str());
+ mP2.mBestAlt = atof(mField[eBestAlt].c_str());
+ mP2.mBestHepe = atof(mField[eBestHepe].c_str());
+ mP2.mBestAltUnc = atof(mField[eBestAltUnc].c_str());
+ }
+
+ inline SystemStatusPQWP2& get() { return mP2;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP3
+******************************************************************************/
+class SystemStatusPQWP3
+{
+public:
+ uint8_t mXtraValidMask;
+ uint32_t mGpsXtraAge;
+ uint32_t mGloXtraAge;
+ uint32_t mBdsXtraAge;
+ uint32_t mGalXtraAge;
+ uint32_t mQzssXtraAge;
+ uint32_t mNavicXtraAge;
+ uint32_t mGpsXtraValid;
+ uint32_t mGloXtraValid;
+ uint64_t mBdsXtraValid;
+ uint64_t mGalXtraValid;
+ uint8_t mQzssXtraValid;
+ uint32_t mNavicXtraValid;
+};
+
+class SystemStatusPQWP3parser : public SystemStatusNmeaBase
+{
+private:
+ // todo: update for navic once available
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eXtraValidMask = 2,
+ eGpsXtraAge = 3,
+ eGloXtraAge = 4,
+ eBdsXtraAge = 5,
+ eGalXtraAge = 6,
+ eQzssXtraAge = 7,
+ eGpsXtraValid = 8,
+ eGloXtraValid = 9,
+ eBdsXtraValid = 10,
+ eGalXtraValid = 11,
+ eQzssXtraValid = 12,
+ eMax
+ };
+ SystemStatusPQWP3 mP3;
+
+public:
+ inline uint8_t getXtraValid() { return mP3.mXtraValidMask; }
+ inline uint32_t getGpsXtraAge() { return mP3.mGpsXtraAge; }
+ inline uint32_t getGloXtraAge() { return mP3.mGloXtraAge; }
+ inline uint32_t getBdsXtraAge() { return mP3.mBdsXtraAge; }
+ inline uint32_t getGalXtraAge() { return mP3.mGalXtraAge; }
+ inline uint32_t getQzssXtraAge() { return mP3.mQzssXtraAge; }
+ inline uint32_t getNavicXtraAge() { return mP3.mNavicXtraAge; }
+ inline uint32_t getGpsXtraValid() { return mP3.mGpsXtraValid; }
+ inline uint32_t getGloXtraValid() { return mP3.mGloXtraValid; }
+ inline uint64_t getBdsXtraValid() { return mP3.mBdsXtraValid; }
+ inline uint64_t getGalXtraValid() { return mP3.mGalXtraValid; }
+ inline uint8_t getQzssXtraValid() { return mP3.mQzssXtraValid; }
+ inline uint32_t getNavicXtraValid() { return mP3.mNavicXtraValid; }
+
+ SystemStatusPQWP3parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP3, 0, sizeof(mP3));
+ // todo: update for navic once available
+ mP3.mXtraValidMask = strtol(mField[eXtraValidMask].c_str(), NULL, 16);
+ mP3.mGpsXtraAge = atoi(mField[eGpsXtraAge].c_str());
+ mP3.mGloXtraAge = atoi(mField[eGloXtraAge].c_str());
+ mP3.mBdsXtraAge = atoi(mField[eBdsXtraAge].c_str());
+ mP3.mGalXtraAge = atoi(mField[eGalXtraAge].c_str());
+ mP3.mQzssXtraAge = atoi(mField[eQzssXtraAge].c_str());
+ mP3.mGpsXtraValid = strtol(mField[eGpsXtraValid].c_str(), NULL, 16);
+ mP3.mGloXtraValid = strtol(mField[eGloXtraValid].c_str(), NULL, 16);
+ mP3.mBdsXtraValid = strtol(mField[eBdsXtraValid].c_str(), NULL, 16);
+ mP3.mGalXtraValid = strtol(mField[eGalXtraValid].c_str(), NULL, 16);
+ mP3.mQzssXtraValid = strtol(mField[eQzssXtraValid].c_str(), NULL, 16);
+ }
+
+ inline SystemStatusPQWP3& get() { return mP3;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP4
+******************************************************************************/
+class SystemStatusPQWP4
+{
+public:
+ uint32_t mGpsEpheValid;
+ uint32_t mGloEpheValid;
+ uint64_t mBdsEpheValid;
+ uint64_t mGalEpheValid;
+ uint8_t mQzssEpheValid;
+};
+
+class SystemStatusPQWP4parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eGpsEpheValid = 2,
+ eGloEpheValid = 3,
+ eBdsEpheValid = 4,
+ eGalEpheValid = 5,
+ eQzssEpheValid = 6,
+ eMax
+ };
+ SystemStatusPQWP4 mP4;
+
+public:
+ inline uint32_t getGpsEpheValid() { return mP4.mGpsEpheValid; }
+ inline uint32_t getGloEpheValid() { return mP4.mGloEpheValid; }
+ inline uint64_t getBdsEpheValid() { return mP4.mBdsEpheValid; }
+ inline uint64_t getGalEpheValid() { return mP4.mGalEpheValid; }
+ inline uint8_t getQzssEpheValid() { return mP4.mQzssEpheValid; }
+
+ SystemStatusPQWP4parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP4, 0, sizeof(mP4));
+ mP4.mGpsEpheValid = strtol(mField[eGpsEpheValid].c_str(), NULL, 16);
+ mP4.mGloEpheValid = strtol(mField[eGloEpheValid].c_str(), NULL, 16);
+ mP4.mBdsEpheValid = strtol(mField[eBdsEpheValid].c_str(), NULL, 16);
+ mP4.mGalEpheValid = strtol(mField[eGalEpheValid].c_str(), NULL, 16);
+ mP4.mQzssEpheValid = strtol(mField[eQzssEpheValid].c_str(), NULL, 16);
+ }
+
+ inline SystemStatusPQWP4& get() { return mP4;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP5
+******************************************************************************/
+class SystemStatusPQWP5
+{
+public:
+ uint32_t mGpsUnknownMask;
+ uint32_t mGloUnknownMask;
+ uint64_t mBdsUnknownMask;
+ uint64_t mGalUnknownMask;
+ uint8_t mQzssUnknownMask;
+ uint32_t mNavicUnknownMask;
+ uint32_t mGpsGoodMask;
+ uint32_t mGloGoodMask;
+ uint64_t mBdsGoodMask;
+ uint64_t mGalGoodMask;
+ uint8_t mQzssGoodMask;
+ uint32_t mNavicGoodMask;
+ uint32_t mGpsBadMask;
+ uint32_t mGloBadMask;
+ uint64_t mBdsBadMask;
+ uint64_t mGalBadMask;
+ uint8_t mQzssBadMask;
+ uint32_t mNavicBadMask;
+};
+
+class SystemStatusPQWP5parser : public SystemStatusNmeaBase
+{
+private:
+ // todo: update for navic once available
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eGpsUnknownMask = 2,
+ eGloUnknownMask = 3,
+ eBdsUnknownMask = 4,
+ eGalUnknownMask = 5,
+ eQzssUnknownMask = 6,
+ eGpsGoodMask = 7,
+ eGloGoodMask = 8,
+ eBdsGoodMask = 9,
+ eGalGoodMask = 10,
+ eQzssGoodMask = 11,
+ eGpsBadMask = 12,
+ eGloBadMask = 13,
+ eBdsBadMask = 14,
+ eGalBadMask = 15,
+ eQzssBadMask = 16,
+ eMax
+ };
+ SystemStatusPQWP5 mP5;
+
+public:
+ inline uint32_t getGpsUnknownMask() { return mP5.mGpsUnknownMask; }
+ inline uint32_t getGloUnknownMask() { return mP5.mGloUnknownMask; }
+ inline uint64_t getBdsUnknownMask() { return mP5.mBdsUnknownMask; }
+ inline uint64_t getGalUnknownMask() { return mP5.mGalUnknownMask; }
+ inline uint8_t getQzssUnknownMask() { return mP5.mQzssUnknownMask; }
+ inline uint32_t getNavicUnknownMask() { return mP5.mNavicUnknownMask; }
+ inline uint32_t getGpsGoodMask() { return mP5.mGpsGoodMask; }
+ inline uint32_t getGloGoodMask() { return mP5.mGloGoodMask; }
+ inline uint64_t getBdsGoodMask() { return mP5.mBdsGoodMask; }
+ inline uint64_t getGalGoodMask() { return mP5.mGalGoodMask; }
+ inline uint8_t getQzssGoodMask() { return mP5.mQzssGoodMask; }
+ inline uint32_t getNavicGoodMask() { return mP5.mNavicGoodMask; }
+ inline uint32_t getGpsBadMask() { return mP5.mGpsBadMask; }
+ inline uint32_t getGloBadMask() { return mP5.mGloBadMask; }
+ inline uint64_t getBdsBadMask() { return mP5.mBdsBadMask; }
+ inline uint64_t getGalBadMask() { return mP5.mGalBadMask; }
+ inline uint8_t getQzssBadMask() { return mP5.mQzssBadMask; }
+ inline uint32_t getNavicBadMask() { return mP5.mNavicBadMask; }
+
+ SystemStatusPQWP5parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP5, 0, sizeof(mP5));
+ // todo: update for navic once available
+ mP5.mGpsUnknownMask = strtol(mField[eGpsUnknownMask].c_str(), NULL, 16);
+ mP5.mGloUnknownMask = strtol(mField[eGloUnknownMask].c_str(), NULL, 16);
+ mP5.mBdsUnknownMask = strtol(mField[eBdsUnknownMask].c_str(), NULL, 16);
+ mP5.mGalUnknownMask = strtol(mField[eGalUnknownMask].c_str(), NULL, 16);
+ mP5.mQzssUnknownMask = strtol(mField[eQzssUnknownMask].c_str(), NULL, 16);
+ mP5.mGpsGoodMask = strtol(mField[eGpsGoodMask].c_str(), NULL, 16);
+ mP5.mGloGoodMask = strtol(mField[eGloGoodMask].c_str(), NULL, 16);
+ mP5.mBdsGoodMask = strtol(mField[eBdsGoodMask].c_str(), NULL, 16);
+ mP5.mGalGoodMask = strtol(mField[eGalGoodMask].c_str(), NULL, 16);
+ mP5.mQzssGoodMask = strtol(mField[eQzssGoodMask].c_str(), NULL, 16);
+ mP5.mGpsBadMask = strtol(mField[eGpsBadMask].c_str(), NULL, 16);
+ mP5.mGloBadMask = strtol(mField[eGloBadMask].c_str(), NULL, 16);
+ mP5.mBdsBadMask = strtol(mField[eBdsBadMask].c_str(), NULL, 16);
+ mP5.mGalBadMask = strtol(mField[eGalBadMask].c_str(), NULL, 16);
+ mP5.mQzssBadMask = strtol(mField[eQzssBadMask].c_str(), NULL, 16);
+ }
+
+ inline SystemStatusPQWP5& get() { return mP5;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP6parser
+******************************************************************************/
+class SystemStatusPQWP6
+{
+public:
+ uint32_t mFixInfoMask;
+};
+
+class SystemStatusPQWP6parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eFixInfoMask = 2,
+ eMax
+ };
+ SystemStatusPQWP6 mP6;
+
+public:
+ inline uint32_t getFixInfoMask() { return mP6.mFixInfoMask; }
+
+ SystemStatusPQWP6parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mP6, 0, sizeof(mP6));
+ mP6.mFixInfoMask = strtol(mField[eFixInfoMask].c_str(), NULL, 16);
+ }
+
+ inline SystemStatusPQWP6& get() { return mP6;}
+};
+
+/******************************************************************************
+ SystemStatusPQWP7parser
+******************************************************************************/
+class SystemStatusPQWP7
+{
+public:
+ SystemStatusNav mNav[SV_ALL_NUM];
+};
+
+class SystemStatusPQWP7parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eMin = 2 + SV_ALL_NUM_MIN*3,
+ eMax = 2 + SV_ALL_NUM*3
+ };
+ SystemStatusPQWP7 mP7;
+
+public:
+ SystemStatusPQWP7parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ uint32_t svLimit = SV_ALL_NUM;
+ if (mField.size() < eMin) {
+ LOC_LOGE("PQWP7parser - invalid size=%zu", mField.size());
+ return;
+ }
+ if (mField.size() < eMax) {
+ // Try reducing limit, accounting for possibly missing NAVIC support
+ svLimit = SV_ALL_NUM_MIN;
+ }
+
+ memset(mP7.mNav, 0, sizeof(mP7.mNav));
+ for (uint32_t i=0; i<svLimit; i++) {
+ mP7.mNav[i].mType = GnssEphemerisType(atoi(mField[i*3+2].c_str()));
+ mP7.mNav[i].mSource = GnssEphemerisSource(atoi(mField[i*3+3].c_str()));
+ mP7.mNav[i].mAgeSec = atoi(mField[i*3+4].c_str());
+ }
+ }
+
+ inline SystemStatusPQWP7& get() { return mP7;}
+};
+
+/******************************************************************************
+ SystemStatusPQWS1parser
+******************************************************************************/
+class SystemStatusPQWS1
+{
+public:
+ uint32_t mFixInfoMask;
+ uint32_t mHepeLimit;
+};
+
+class SystemStatusPQWS1parser : public SystemStatusNmeaBase
+{
+private:
+ enum
+ {
+ eTalker = 0,
+ eUtcTime = 1,
+ eFixInfoMask = 2,
+ eHepeLimit = 3,
+ eMax
+ };
+ SystemStatusPQWS1 mS1;
+
+public:
+ inline uint16_t getFixInfoMask() { return mS1.mFixInfoMask; }
+ inline uint32_t getHepeLimit() { return mS1.mHepeLimit; }
+
+ SystemStatusPQWS1parser(const char *str_in, uint32_t len_in)
+ : SystemStatusNmeaBase(str_in, len_in)
+ {
+ if (mField.size() < eMax) {
+ return;
+ }
+ memset(&mS1, 0, sizeof(mS1));
+ mS1.mFixInfoMask = atoi(mField[eFixInfoMask].c_str());
+ mS1.mHepeLimit = atoi(mField[eHepeLimit].c_str());
+ }
+
+ inline SystemStatusPQWS1& get() { return mS1;}
+};
+
+/******************************************************************************
+ SystemStatusTimeAndClock
+******************************************************************************/
+SystemStatusTimeAndClock::SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea) :
+ mGpsWeek(nmea.mGpsWeek),
+ mGpsTowMs(nmea.mGpsTowMs),
+ mTimeValid(nmea.mTimeValid),
+ mTimeSource(nmea.mTimeSource),
+ mTimeUnc(nmea.mTimeUnc),
+ mClockFreqBias(nmea.mClockFreqBias),
+ mClockFreqBiasUnc(nmea.mClockFreqBiasUnc),
+ mLeapSeconds(nmea.mLeapSeconds),
+ mLeapSecUnc(nmea.mLeapSecUnc),
+ mTimeUncNs(nmea.mTimeUncNs)
+{
+}
+
+bool SystemStatusTimeAndClock::equals(const SystemStatusTimeAndClock& peer)
+{
+ if ((mGpsWeek != peer.mGpsWeek) ||
+ (mGpsTowMs != peer.mGpsTowMs) ||
+ (mTimeValid != peer.mTimeValid) ||
+ (mTimeSource != peer.mTimeSource) ||
+ (mTimeUnc != peer.mTimeUnc) ||
+ (mClockFreqBias != peer.mClockFreqBias) ||
+ (mClockFreqBiasUnc != peer.mClockFreqBiasUnc) ||
+ (mLeapSeconds != peer.mLeapSeconds) ||
+ (mLeapSecUnc != peer.mLeapSecUnc) ||
+ (mTimeUncNs != peer.mTimeUncNs)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusTimeAndClock::dump()
+{
+ LOC_LOGV("TimeAndClock: u=%ld:%ld g=%d:%d v=%d ts=%d tu=%d b=%d bu=%d ls=%d lu=%d un=%" PRIu64,
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mGpsWeek,
+ mGpsTowMs,
+ mTimeValid,
+ mTimeSource,
+ mTimeUnc,
+ mClockFreqBias,
+ mClockFreqBiasUnc,
+ mLeapSeconds,
+ mLeapSecUnc,
+ mTimeUncNs);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusXoState
+******************************************************************************/
+SystemStatusXoState::SystemStatusXoState(const SystemStatusPQWM1& nmea) :
+ mXoState(nmea.mXoState)
+{
+}
+
+bool SystemStatusXoState::equals(const SystemStatusXoState& peer)
+{
+ if (mXoState != peer.mXoState) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusXoState::dump()
+{
+ LOC_LOGV("XoState: u=%ld:%ld x=%d",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mXoState);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusRfAndParams
+******************************************************************************/
+SystemStatusRfAndParams::SystemStatusRfAndParams(const SystemStatusPQWM1& nmea) :
+ mPgaGain(nmea.mPgaGain),
+ mGpsBpAmpI(nmea.mGpsBpAmpI),
+ mGpsBpAmpQ(nmea.mGpsBpAmpQ),
+ mAdcI(nmea.mAdcI),
+ mAdcQ(nmea.mAdcQ),
+ mJammerGps(nmea.mJammerGps),
+ mJammerGlo(nmea.mJammerGlo),
+ mJammerBds(nmea.mJammerBds),
+ mJammerGal(nmea.mJammerGal),
+ mAgcGps(nmea.mAgcGps),
+ mAgcGlo(nmea.mAgcGlo),
+ mAgcBds(nmea.mAgcBds),
+ mAgcGal(nmea.mAgcGal),
+ mGloBpAmpI(nmea.mGloBpAmpI),
+ mGloBpAmpQ(nmea.mGloBpAmpQ),
+ mBdsBpAmpI(nmea.mBdsBpAmpI),
+ mBdsBpAmpQ(nmea.mBdsBpAmpQ),
+ mGalBpAmpI(nmea.mGalBpAmpI),
+ mGalBpAmpQ(nmea.mGalBpAmpQ)
+{
+}
+
+bool SystemStatusRfAndParams::equals(const SystemStatusRfAndParams& peer)
+{
+ if ((mPgaGain != peer.mPgaGain) ||
+ (mGpsBpAmpI != peer.mGpsBpAmpI) ||
+ (mGpsBpAmpQ != peer.mGpsBpAmpQ) ||
+ (mAdcI != peer.mAdcI) ||
+ (mAdcQ != peer.mAdcQ) ||
+ (mJammerGps != peer.mJammerGps) ||
+ (mJammerGlo != peer.mJammerGlo) ||
+ (mJammerBds != peer.mJammerBds) ||
+ (mJammerGal != peer.mJammerGal) ||
+ (mAgcGps != peer.mAgcGps) ||
+ (mAgcGlo != peer.mAgcGlo) ||
+ (mAgcBds != peer.mAgcBds) ||
+ (mAgcGal != peer.mAgcGal) ||
+ (mGloBpAmpI != peer.mGloBpAmpI) ||
+ (mGloBpAmpQ != peer.mGloBpAmpQ) ||
+ (mBdsBpAmpI != peer.mBdsBpAmpI) ||
+ (mBdsBpAmpQ != peer.mBdsBpAmpQ) ||
+ (mGalBpAmpI != peer.mGalBpAmpI) ||
+ (mGalBpAmpQ != peer.mGalBpAmpQ)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusRfAndParams::dump()
+{
+ LOC_LOGV("RfAndParams: u=%ld:%ld p=%d bi=%d bq=%d ai=%d aq=%d "
+ "jgp=%d jgl=%d jbd=%d jga=%d "
+ "agp=%lf agl=%lf abd=%lf aga=%lf",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mPgaGain,
+ mGpsBpAmpI,
+ mGpsBpAmpQ,
+ mAdcI,
+ mAdcQ,
+ mJammerGps,
+ mJammerGlo,
+ mJammerBds,
+ mJammerGal,
+ mAgcGps,
+ mAgcGlo,
+ mAgcBds,
+ mAgcGal);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusErrRecovery
+******************************************************************************/
+SystemStatusErrRecovery::SystemStatusErrRecovery(const SystemStatusPQWM1& nmea) :
+ mRecErrorRecovery(nmea.mRecErrorRecovery)
+{
+}
+
+bool SystemStatusErrRecovery::equals(const SystemStatusErrRecovery& peer)
+{
+ if (mRecErrorRecovery != peer.mRecErrorRecovery) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusErrRecovery::dump()
+{
+ LOC_LOGV("ErrRecovery: u=%ld:%ld e=%d",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mRecErrorRecovery);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusInjectedPosition
+******************************************************************************/
+SystemStatusInjectedPosition::SystemStatusInjectedPosition(const SystemStatusPQWP1& nmea) :
+ mEpiValidity(nmea.mEpiValidity),
+ mEpiLat(nmea.mEpiLat),
+ mEpiLon(nmea.mEpiLon),
+ mEpiAlt(nmea.mEpiAlt),
+ mEpiHepe(nmea.mEpiHepe),
+ mEpiAltUnc(nmea.mEpiAltUnc),
+ mEpiSrc(nmea.mEpiSrc)
+{
+}
+
+bool SystemStatusInjectedPosition::equals(const SystemStatusInjectedPosition& peer)
+{
+ if ((mEpiValidity != peer.mEpiValidity) ||
+ (mEpiLat != peer.mEpiLat) ||
+ (mEpiLon != peer.mEpiLon) ||
+ (mEpiAlt != peer.mEpiAlt) ||
+ (mEpiHepe != peer.mEpiHepe) ||
+ (mEpiAltUnc != peer.mEpiAltUnc) ||
+ (mEpiSrc != peer.mEpiSrc)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusInjectedPosition::dump()
+{
+ LOC_LOGV("InjectedPosition: u=%ld:%ld v=%x la=%f lo=%f al=%f he=%f au=%f es=%d",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mEpiValidity,
+ mEpiLat,
+ mEpiLon,
+ mEpiAlt,
+ mEpiHepe,
+ mEpiAltUnc,
+ mEpiSrc);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusBestPosition
+******************************************************************************/
+SystemStatusBestPosition::SystemStatusBestPosition(const SystemStatusPQWP2& nmea) :
+ mValid(true),
+ mBestLat(nmea.mBestLat),
+ mBestLon(nmea.mBestLon),
+ mBestAlt(nmea.mBestAlt),
+ mBestHepe(nmea.mBestHepe),
+ mBestAltUnc(nmea.mBestAltUnc)
+{
+}
+
+bool SystemStatusBestPosition::equals(const SystemStatusBestPosition& peer)
+{
+ if ((mBestLat != peer.mBestLat) ||
+ (mBestLon != peer.mBestLon) ||
+ (mBestAlt != peer.mBestAlt) ||
+ (mBestHepe != peer.mBestHepe) ||
+ (mBestAltUnc != peer.mBestAltUnc)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusBestPosition::dump()
+{
+ LOC_LOGV("BestPosition: u=%ld:%ld la=%f lo=%f al=%f he=%f au=%f",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mBestLat,
+ mBestLon,
+ mBestAlt,
+ mBestHepe,
+ mBestAltUnc);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusXtra
+******************************************************************************/
+SystemStatusXtra::SystemStatusXtra(const SystemStatusPQWP3& nmea) :
+ mXtraValidMask(nmea.mXtraValidMask),
+ mGpsXtraAge(nmea.mGpsXtraAge),
+ mGloXtraAge(nmea.mGloXtraAge),
+ mBdsXtraAge(nmea.mBdsXtraAge),
+ mGalXtraAge(nmea.mGalXtraAge),
+ mQzssXtraAge(nmea.mQzssXtraAge),
+ mNavicXtraAge(nmea.mNavicXtraAge),
+ mGpsXtraValid(nmea.mGpsXtraValid),
+ mGloXtraValid(nmea.mGloXtraValid),
+ mBdsXtraValid(nmea.mBdsXtraValid),
+ mGalXtraValid(nmea.mGalXtraValid),
+ mQzssXtraValid(nmea.mQzssXtraValid),
+ mNavicXtraValid(nmea.mNavicXtraValid)
+{
+}
+
+bool SystemStatusXtra::equals(const SystemStatusXtra& peer)
+{
+ if ((mXtraValidMask != peer.mXtraValidMask) ||
+ (mGpsXtraAge != peer.mGpsXtraAge) ||
+ (mGloXtraAge != peer.mGloXtraAge) ||
+ (mBdsXtraAge != peer.mBdsXtraAge) ||
+ (mGalXtraAge != peer.mGalXtraAge) ||
+ (mQzssXtraAge != peer.mQzssXtraAge) ||
+ (mNavicXtraAge != peer.mNavicXtraAge) ||
+ (mGpsXtraValid != peer.mGpsXtraValid) ||
+ (mGloXtraValid != peer.mGloXtraValid) ||
+ (mBdsXtraValid != peer.mBdsXtraValid) ||
+ (mGalXtraValid != peer.mGalXtraValid) ||
+ (mQzssXtraValid != peer.mQzssXtraValid) ||
+ (mNavicXtraValid != peer.mNavicXtraValid)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusXtra::dump()
+{
+ LOC_LOGV("SystemStatusXtra: u=%ld:%ld m=%x a=%d:%d:%d:%d:%d v=%x:%x:%" PRIx64 ":%" PRIx64":%x",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mXtraValidMask,
+ mGpsXtraAge,
+ mGloXtraAge,
+ mBdsXtraAge,
+ mGalXtraAge,
+ mQzssXtraAge,
+ mGpsXtraValid,
+ mGloXtraValid,
+ mBdsXtraValid,
+ mGalXtraValid,
+ mQzssXtraValid);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusEphemeris
+******************************************************************************/
+SystemStatusEphemeris::SystemStatusEphemeris(const SystemStatusPQWP4& nmea) :
+ mGpsEpheValid(nmea.mGpsEpheValid),
+ mGloEpheValid(nmea.mGloEpheValid),
+ mBdsEpheValid(nmea.mBdsEpheValid),
+ mGalEpheValid(nmea.mGalEpheValid),
+ mQzssEpheValid(nmea.mQzssEpheValid)
+{
+}
+
+bool SystemStatusEphemeris::equals(const SystemStatusEphemeris& peer)
+{
+ if ((mGpsEpheValid != peer.mGpsEpheValid) ||
+ (mGloEpheValid != peer.mGloEpheValid) ||
+ (mBdsEpheValid != peer.mBdsEpheValid) ||
+ (mGalEpheValid != peer.mGalEpheValid) ||
+ (mQzssEpheValid != peer.mQzssEpheValid)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusEphemeris::dump()
+{
+ LOC_LOGV("Ephemeris: u=%ld:%ld ev=%x:%x:%" PRIx64 ":%" PRIx64 ":%x",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mGpsEpheValid,
+ mGloEpheValid,
+ mBdsEpheValid,
+ mGalEpheValid,
+ mQzssEpheValid);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusSvHealth
+******************************************************************************/
+SystemStatusSvHealth::SystemStatusSvHealth(const SystemStatusPQWP5& nmea) :
+ mGpsUnknownMask(nmea.mGpsUnknownMask),
+ mGloUnknownMask(nmea.mGloUnknownMask),
+ mBdsUnknownMask(nmea.mBdsUnknownMask),
+ mGalUnknownMask(nmea.mGalUnknownMask),
+ mQzssUnknownMask(nmea.mQzssUnknownMask),
+ mNavicUnknownMask(nmea.mNavicUnknownMask),
+ mGpsGoodMask(nmea.mGpsGoodMask),
+ mGloGoodMask(nmea.mGloGoodMask),
+ mBdsGoodMask(nmea.mBdsGoodMask),
+ mGalGoodMask(nmea.mGalGoodMask),
+ mQzssGoodMask(nmea.mQzssGoodMask),
+ mNavicGoodMask(nmea.mNavicGoodMask),
+ mGpsBadMask(nmea.mGpsBadMask),
+ mGloBadMask(nmea.mGloBadMask),
+ mBdsBadMask(nmea.mBdsBadMask),
+ mGalBadMask(nmea.mGalBadMask),
+ mQzssBadMask(nmea.mQzssBadMask),
+ mNavicBadMask(nmea.mNavicBadMask)
+{
+}
+
+bool SystemStatusSvHealth::equals(const SystemStatusSvHealth& peer)
+{
+ if ((mGpsUnknownMask != peer.mGpsUnknownMask) ||
+ (mGloUnknownMask != peer.mGloUnknownMask) ||
+ (mBdsUnknownMask != peer.mBdsUnknownMask) ||
+ (mGalUnknownMask != peer.mGalUnknownMask) ||
+ (mQzssUnknownMask != peer.mQzssUnknownMask) ||
+ (mGpsGoodMask != peer.mGpsGoodMask) ||
+ (mGloGoodMask != peer.mGloGoodMask) ||
+ (mBdsGoodMask != peer.mBdsGoodMask) ||
+ (mGalGoodMask != peer.mGalGoodMask) ||
+ (mQzssGoodMask != peer.mQzssGoodMask) ||
+ (mGpsBadMask != peer.mGpsBadMask) ||
+ (mGloBadMask != peer.mGloBadMask) ||
+ (mBdsBadMask != peer.mBdsBadMask) ||
+ (mGalBadMask != peer.mGalBadMask) ||
+ (mQzssBadMask != peer.mQzssBadMask)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusSvHealth::dump()
+{
+ LOC_LOGV("SvHealth: u=%ld:%ld \
+ u=%x:%x:%" PRIx64 ":%" PRIx64 ":%x \
+ g=%x:%x:%" PRIx64 ":%" PRIx64 ":%x \
+ b=%x:%x:%" PRIx64 ":%" PRIx64 ":%x",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mGpsUnknownMask,
+ mGloUnknownMask,
+ mBdsUnknownMask,
+ mGalUnknownMask,
+ mQzssUnknownMask,
+ mGpsGoodMask,
+ mGloGoodMask,
+ mBdsGoodMask,
+ mGalGoodMask,
+ mQzssGoodMask,
+ mGpsBadMask,
+ mGloBadMask,
+ mBdsBadMask,
+ mGalBadMask,
+ mQzssBadMask);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusPdr
+******************************************************************************/
+SystemStatusPdr::SystemStatusPdr(const SystemStatusPQWP6& nmea) :
+ mFixInfoMask(nmea.mFixInfoMask)
+{
+}
+
+bool SystemStatusPdr::equals(const SystemStatusPdr& peer)
+{
+ if (mFixInfoMask != peer.mFixInfoMask) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusPdr::dump()
+{
+ LOC_LOGV("Pdr: u=%ld:%ld m=%x",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mFixInfoMask);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusNavData
+******************************************************************************/
+SystemStatusNavData::SystemStatusNavData(const SystemStatusPQWP7& nmea)
+{
+ for (uint32_t i=0; i<SV_ALL_NUM; i++) {
+ mNav[i] = nmea.mNav[i];
+ }
+}
+
+bool SystemStatusNavData::equals(const SystemStatusNavData& peer)
+{
+ for (uint32_t i=0; i<SV_ALL_NUM; i++) {
+ if ((mNav[i].mType != peer.mNav[i].mType) ||
+ (mNav[i].mSource != peer.mNav[i].mSource) ||
+ (mNav[i].mAgeSec != peer.mNav[i].mAgeSec)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SystemStatusNavData::dump()
+{
+ LOC_LOGV("NavData: u=%ld:%ld",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec);
+ for (uint32_t i=0; i<SV_ALL_NUM; i++) {
+ LOC_LOGV("i=%d type=%d src=%d age=%d",
+ i, mNav[i].mType, mNav[i].mSource, mNav[i].mAgeSec);
+ }
+ return;
+}
+
+/******************************************************************************
+ SystemStatusPositionFailure
+******************************************************************************/
+SystemStatusPositionFailure::SystemStatusPositionFailure(const SystemStatusPQWS1& nmea) :
+ mFixInfoMask(nmea.mFixInfoMask),
+ mHepeLimit(nmea.mHepeLimit)
+{
+}
+
+bool SystemStatusPositionFailure::equals(const SystemStatusPositionFailure& peer)
+{
+ if ((mFixInfoMask != peer.mFixInfoMask) ||
+ (mHepeLimit != peer.mHepeLimit)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusPositionFailure::dump()
+{
+ LOC_LOGV("PositionFailure: u=%ld:%ld m=%d h=%d",
+ mUtcTime.tv_sec, mUtcTime.tv_nsec,
+ mFixInfoMask,
+ mHepeLimit);
+ return;
+}
+
+/******************************************************************************
+ SystemStatusLocation
+******************************************************************************/
+bool SystemStatusLocation::equals(const SystemStatusLocation& peer)
+{
+ if ((mLocation.gpsLocation.latitude != peer.mLocation.gpsLocation.latitude) ||
+ (mLocation.gpsLocation.longitude != peer.mLocation.gpsLocation.longitude) ||
+ (mLocation.gpsLocation.altitude != peer.mLocation.gpsLocation.altitude)) {
+ return false;
+ }
+ return true;
+}
+
+void SystemStatusLocation::dump()
+{
+ LOC_LOGV("Location: lat=%f lon=%f alt=%f spd=%f",
+ mLocation.gpsLocation.latitude,
+ mLocation.gpsLocation.longitude,
+ mLocation.gpsLocation.altitude,
+ mLocation.gpsLocation.speed);
+ return;
+}
+
+/******************************************************************************
+ SystemStatus
+******************************************************************************/
+pthread_mutex_t SystemStatus::mMutexSystemStatus = PTHREAD_MUTEX_INITIALIZER;
+SystemStatus* SystemStatus::mInstance = NULL;
+
+SystemStatus* SystemStatus::getInstance(const MsgTask* msgTask)
+{
+ pthread_mutex_lock(&mMutexSystemStatus);
+
+ if (!mInstance) {
+ // Instantiating for the first time. msgTask should not be NULL
+ if (msgTask == NULL) {
+ LOC_LOGE("SystemStatus: msgTask is NULL!!");
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return NULL;
+ }
+ mInstance = new (nothrow) SystemStatus(msgTask);
+ LOC_LOGD("SystemStatus::getInstance:%p. Msgtask:%p", mInstance, msgTask);
+ }
+
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return mInstance;
+}
+
+void SystemStatus::destroyInstance()
+{
+ delete mInstance;
+ mInstance = NULL;
+}
+
+void SystemStatus::resetNetworkInfo() {
+ for (int i=0; i<mCache.mNetworkInfo.size(); ++i) {
+ // Reset all the cached NetworkInfo Items as disconnected
+ eventConnectionStatus(false, mCache.mNetworkInfo[i].mType, mCache.mNetworkInfo[i].mRoaming,
+ mCache.mNetworkInfo[i].mNetworkHandle, mCache.mNetworkInfo[i].mApn);
+ }
+}
+
+IOsObserver* SystemStatus::getOsObserver()
+{
+ return &mSysStatusObsvr;
+}
+
+SystemStatus::SystemStatus(const MsgTask* msgTask) :
+ mSysStatusObsvr(this, msgTask)
+{
+ int result = 0;
+ ENTRY_LOG ();
+ mCache.mLocation.clear();
+
+ mCache.mTimeAndClock.clear();
+ mCache.mXoState.clear();
+ mCache.mRfAndParams.clear();
+ mCache.mErrRecovery.clear();
+
+ mCache.mInjectedPosition.clear();
+ mCache.mBestPosition.clear();
+ mCache.mXtra.clear();
+ mCache.mEphemeris.clear();
+ mCache.mSvHealth.clear();
+ mCache.mPdr.clear();
+ mCache.mNavData.clear();
+
+ mCache.mPositionFailure.clear();
+
+ mCache.mAirplaneMode.clear();
+ mCache.mENH.clear();
+ mCache.mGPSState.clear();
+ mCache.mNLPStatus.clear();
+ mCache.mWifiHardwareState.clear();
+ mCache.mNetworkInfo.clear();
+ mCache.mRilServiceInfo.clear();
+ mCache.mRilCellInfo.clear();
+ mCache.mServiceStatus.clear();
+ mCache.mModel.clear();
+ mCache.mManufacturer.clear();
+ mCache.mAssistedGps.clear();
+ mCache.mScreenState.clear();
+ mCache.mPowerConnectState.clear();
+ mCache.mTimeZoneChange.clear();
+ mCache.mTimeChange.clear();
+ mCache.mWifiSupplicantStatus.clear();
+ mCache.mShutdownState.clear();
+ mCache.mTac.clear();
+ mCache.mMccMnc.clear();
+ mCache.mBtDeviceScanDetail.clear();
+ mCache.mBtLeDeviceScanDetail.clear();
+
+ EXIT_LOG_WITH_ERROR ("%d",result);
+}
+
+/******************************************************************************
+ SystemStatus - storing dataitems
+******************************************************************************/
+template <typename TYPE_REPORT, typename TYPE_ITEM>
+bool SystemStatus::setIteminReport(TYPE_REPORT& report, TYPE_ITEM&& s)
+{
+ if (s.ignore()) {
+ return false;
+ }
+ if (!report.empty() && report.back().equals(static_cast<TYPE_ITEM&>(s.collate(report.back())))) {
+ // there is no change - just update reported timestamp
+ report.back().mUtcReported = s.mUtcReported;
+ return false;
+ }
+
+ // first event or updated
+ report.push_back(s);
+ if (report.size() > s.maxItem) {
+ report.erase(report.begin());
+ }
+ return true;
+}
+
+template <typename TYPE_REPORT, typename TYPE_ITEM>
+void SystemStatus::setDefaultIteminReport(TYPE_REPORT& report, const TYPE_ITEM& s)
+{
+ report.push_back(s);
+ if (report.size() > s.maxItem) {
+ report.erase(report.begin());
+ }
+}
+
+template <typename TYPE_REPORT, typename TYPE_ITEM>
+void SystemStatus::getIteminReport(TYPE_REPORT& reportout, const TYPE_ITEM& c) const
+{
+ reportout.clear();
+ if (c.size() >= 1) {
+ reportout.push_back(c.back());
+ reportout.back().dump();
+ }
+}
+
+/******************************************************************************
+@brief API to set report data into internal buffer
+
+@param[In] data pointer to the NMEA string
+@param[In] len length of the NMEA string
+
+@return true when the NMEA is consumed by the method.
+******************************************************************************/
+bool SystemStatus::setNmeaString(const char *data, uint32_t len)
+{
+ if (!loc_nmea_is_debug(data, len)) {
+ return false;
+ }
+
+ char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 };
+ strlcpy(buf, data, sizeof(buf));
+
+ pthread_mutex_lock(&mMutexSystemStatus);
+
+ // parse the received nmea strings here
+ if (0 == strncmp(data, "$PQWM1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ SystemStatusPQWM1 s = SystemStatusPQWM1parser(buf, len).get();
+ setIteminReport(mCache.mTimeAndClock, SystemStatusTimeAndClock(s));
+ setIteminReport(mCache.mXoState, SystemStatusXoState(s));
+ setIteminReport(mCache.mRfAndParams, SystemStatusRfAndParams(s));
+ setIteminReport(mCache.mErrRecovery, SystemStatusErrRecovery(s));
+ }
+ else if (0 == strncmp(data, "$PQWP1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mInjectedPosition,
+ SystemStatusInjectedPosition(SystemStatusPQWP1parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP2", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mBestPosition,
+ SystemStatusBestPosition(SystemStatusPQWP2parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP3", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mXtra,
+ SystemStatusXtra(SystemStatusPQWP3parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP4", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mEphemeris,
+ SystemStatusEphemeris(SystemStatusPQWP4parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP5", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mSvHealth,
+ SystemStatusSvHealth(SystemStatusPQWP5parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP6", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mPdr,
+ SystemStatusPdr(SystemStatusPQWP6parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWP7", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mNavData,
+ SystemStatusNavData(SystemStatusPQWP7parser(buf, len).get()));
+ }
+ else if (0 == strncmp(data, "$PQWS1", SystemStatusNmeaBase::NMEA_MINSIZE)) {
+ setIteminReport(mCache.mPositionFailure,
+ SystemStatusPositionFailure(SystemStatusPQWS1parser(buf, len).get()));
+ }
+ else {
+ // do nothing
+ }
+
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return true;
+}
+
+/******************************************************************************
+@brief API to set report position data into internal buffer
+
+@param[In] UlpLocation
+
+@return true when successfully done
+******************************************************************************/
+bool SystemStatus::eventPosition(const UlpLocation& location,
+ const GpsLocationExtended& locationEx)
+{
+ bool ret = false;
+ pthread_mutex_lock(&mMutexSystemStatus);
+
+ ret = setIteminReport(mCache.mLocation, SystemStatusLocation(location, locationEx));
+ LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f",
+ location.gpsLocation.latitude,
+ location.gpsLocation.longitude,
+ location.gpsLocation.altitude,
+ location.gpsLocation.speed);
+
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return ret;
+}
+
+/******************************************************************************
+@brief API to set report DataItem event into internal buffer
+
+@param[In] DataItem
+
+@return true when info is updatated
+******************************************************************************/
+bool SystemStatus::eventDataItemNotify(IDataItemCore* dataitem)
+{
+ bool ret = false;
+ pthread_mutex_lock(&mMutexSystemStatus);
+ switch(dataitem->getId())
+ {
+ case AIRPLANEMODE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mAirplaneMode,
+ SystemStatusAirplaneMode(*(static_cast<AirplaneModeDataItemBase*>(dataitem))));
+ break;
+ case ENH_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mENH,
+ SystemStatusENH(*(static_cast<ENHDataItemBase*>(dataitem))));
+ break;
+ case GPSSTATE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mGPSState,
+ SystemStatusGpsState(*(static_cast<GPSStateDataItemBase*>(dataitem))));
+ break;
+ case NLPSTATUS_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mNLPStatus,
+ SystemStatusNLPStatus(*(static_cast<NLPStatusDataItemBase*>(dataitem))));
+ break;
+ case WIFIHARDWARESTATE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mWifiHardwareState,
+ SystemStatusWifiHardwareState(*(static_cast<WifiHardwareStateDataItemBase*>(dataitem))));
+ break;
+ case NETWORKINFO_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mNetworkInfo,
+ SystemStatusNetworkInfo(*(static_cast<NetworkInfoDataItemBase*>(dataitem))));
+ break;
+ case RILSERVICEINFO_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mRilServiceInfo,
+ SystemStatusServiceInfo(*(static_cast<RilServiceInfoDataItemBase*>(dataitem))));
+ break;
+ case RILCELLINFO_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mRilCellInfo,
+ SystemStatusRilCellInfo(*(static_cast<RilCellInfoDataItemBase*>(dataitem))));
+ break;
+ case SERVICESTATUS_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mServiceStatus,
+ SystemStatusServiceStatus(*(static_cast<ServiceStatusDataItemBase*>(dataitem))));
+ break;
+ case MODEL_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mModel,
+ SystemStatusModel(*(static_cast<ModelDataItemBase*>(dataitem))));
+ break;
+ case MANUFACTURER_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mManufacturer,
+ SystemStatusManufacturer(*(static_cast<ManufacturerDataItemBase*>(dataitem))));
+ break;
+ case ASSISTED_GPS_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mAssistedGps,
+ SystemStatusAssistedGps(*(static_cast<AssistedGpsDataItemBase*>(dataitem))));
+ break;
+ case SCREEN_STATE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mScreenState,
+ SystemStatusScreenState(*(static_cast<ScreenStateDataItemBase*>(dataitem))));
+ break;
+ case POWER_CONNECTED_STATE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mPowerConnectState,
+ SystemStatusPowerConnectState(*(static_cast<PowerConnectStateDataItemBase*>(dataitem))));
+ break;
+ case TIMEZONE_CHANGE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mTimeZoneChange,
+ SystemStatusTimeZoneChange(*(static_cast<TimeZoneChangeDataItemBase*>(dataitem))));
+ break;
+ case TIME_CHANGE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mTimeChange,
+ SystemStatusTimeChange(*(static_cast<TimeChangeDataItemBase*>(dataitem))));
+ break;
+ case WIFI_SUPPLICANT_STATUS_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mWifiSupplicantStatus,
+ SystemStatusWifiSupplicantStatus(*(static_cast<WifiSupplicantStatusDataItemBase*>(dataitem))));
+ break;
+ case SHUTDOWN_STATE_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mShutdownState,
+ SystemStatusShutdownState(*(static_cast<ShutdownStateDataItemBase*>(dataitem))));
+ break;
+ case TAC_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mTac,
+ SystemStatusTac(*(static_cast<TacDataItemBase*>(dataitem))));
+ break;
+ case MCCMNC_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mMccMnc,
+ SystemStatusMccMnc(*(static_cast<MccmncDataItemBase*>(dataitem))));
+ break;
+ case BTLE_SCAN_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mBtDeviceScanDetail,
+ SystemStatusBtDeviceScanDetail(*(static_cast<BtDeviceScanDetailsDataItemBase*>(dataitem))));
+ break;
+ case BT_SCAN_DATA_ITEM_ID:
+ ret = setIteminReport(mCache.mBtLeDeviceScanDetail,
+ SystemStatusBtleDeviceScanDetail(*(static_cast<BtLeDeviceScanDetailsDataItemBase*>(dataitem))));
+ break;
+ default:
+ break;
+ }
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return ret;
+}
+
+/******************************************************************************
+@brief API to get report data into a given buffer
+
+@param[In] reference to report buffer
+@param[In] bool flag to identify latest only or entire buffer
+
+@return true when successfully done
+******************************************************************************/
+bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) const
+{
+ pthread_mutex_lock(&mMutexSystemStatus);
+
+ if (isLatestOnly) {
+ // push back only the latest report and return it
+ getIteminReport(report.mLocation, mCache.mLocation);
+
+ getIteminReport(report.mTimeAndClock, mCache.mTimeAndClock);
+ getIteminReport(report.mXoState, mCache.mXoState);
+ getIteminReport(report.mRfAndParams, mCache.mRfAndParams);
+ getIteminReport(report.mErrRecovery, mCache.mErrRecovery);
+
+ getIteminReport(report.mInjectedPosition, mCache.mInjectedPosition);
+ getIteminReport(report.mBestPosition, mCache.mBestPosition);
+ getIteminReport(report.mXtra, mCache.mXtra);
+ getIteminReport(report.mEphemeris, mCache.mEphemeris);
+ getIteminReport(report.mSvHealth, mCache.mSvHealth);
+ getIteminReport(report.mPdr, mCache.mPdr);
+ getIteminReport(report.mNavData, mCache.mNavData);
+
+ getIteminReport(report.mPositionFailure, mCache.mPositionFailure);
+
+ getIteminReport(report.mAirplaneMode, mCache.mAirplaneMode);
+ getIteminReport(report.mENH, mCache.mENH);
+ getIteminReport(report.mGPSState, mCache.mGPSState);
+ getIteminReport(report.mNLPStatus, mCache.mNLPStatus);
+ getIteminReport(report.mWifiHardwareState, mCache.mWifiHardwareState);
+ getIteminReport(report.mNetworkInfo, mCache.mNetworkInfo);
+ getIteminReport(report.mRilServiceInfo, mCache.mRilServiceInfo);
+ getIteminReport(report.mRilCellInfo, mCache.mRilCellInfo);
+ getIteminReport(report.mServiceStatus, mCache.mServiceStatus);
+ getIteminReport(report.mModel, mCache.mModel);
+ getIteminReport(report.mManufacturer, mCache.mManufacturer);
+ getIteminReport(report.mAssistedGps, mCache.mAssistedGps);
+ getIteminReport(report.mScreenState, mCache.mScreenState);
+ getIteminReport(report.mPowerConnectState, mCache.mPowerConnectState);
+ getIteminReport(report.mTimeZoneChange, mCache.mTimeZoneChange);
+ getIteminReport(report.mTimeChange, mCache.mTimeChange);
+ getIteminReport(report.mWifiSupplicantStatus, mCache.mWifiSupplicantStatus);
+ getIteminReport(report.mShutdownState, mCache.mShutdownState);
+ getIteminReport(report.mTac, mCache.mTac);
+ getIteminReport(report.mMccMnc, mCache.mMccMnc);
+ getIteminReport(report.mBtDeviceScanDetail, mCache.mBtDeviceScanDetail);
+ getIteminReport(report.mBtLeDeviceScanDetail, mCache.mBtLeDeviceScanDetail);
+ }
+ else {
+ // copy entire reports and return them
+ report.mLocation.clear();
+
+ report.mTimeAndClock.clear();
+ report.mXoState.clear();
+ report.mRfAndParams.clear();
+ report.mErrRecovery.clear();
+
+ report.mInjectedPosition.clear();
+ report.mBestPosition.clear();
+ report.mXtra.clear();
+ report.mEphemeris.clear();
+ report.mSvHealth.clear();
+ report.mPdr.clear();
+ report.mNavData.clear();
+
+ report.mPositionFailure.clear();
+
+ report.mAirplaneMode.clear();
+ report.mENH.clear();
+ report.mGPSState.clear();
+ report.mNLPStatus.clear();
+ report.mWifiHardwareState.clear();
+ report.mNetworkInfo.clear();
+ report.mRilServiceInfo.clear();
+ report.mRilCellInfo.clear();
+ report.mServiceStatus.clear();
+ report.mModel.clear();
+ report.mManufacturer.clear();
+ report.mAssistedGps.clear();
+ report.mScreenState.clear();
+ report.mPowerConnectState.clear();
+ report.mTimeZoneChange.clear();
+ report.mTimeChange.clear();
+ report.mWifiSupplicantStatus.clear();
+ report.mShutdownState.clear();
+ report.mTac.clear();
+ report.mMccMnc.clear();
+ report.mBtDeviceScanDetail.clear();
+ report.mBtLeDeviceScanDetail.clear();
+
+ report = mCache;
+ }
+
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return true;
+}
+
+/******************************************************************************
+@brief API to set default report data
+
+@param[In] none
+
+@return true when successfully done
+******************************************************************************/
+bool SystemStatus::setDefaultGnssEngineStates(void)
+{
+ pthread_mutex_lock(&mMutexSystemStatus);
+
+ setDefaultIteminReport(mCache.mLocation, SystemStatusLocation());
+
+ setDefaultIteminReport(mCache.mTimeAndClock, SystemStatusTimeAndClock());
+ setDefaultIteminReport(mCache.mXoState, SystemStatusXoState());
+ setDefaultIteminReport(mCache.mRfAndParams, SystemStatusRfAndParams());
+ setDefaultIteminReport(mCache.mErrRecovery, SystemStatusErrRecovery());
+
+ setDefaultIteminReport(mCache.mInjectedPosition, SystemStatusInjectedPosition());
+ setDefaultIteminReport(mCache.mBestPosition, SystemStatusBestPosition());
+ setDefaultIteminReport(mCache.mXtra, SystemStatusXtra());
+ setDefaultIteminReport(mCache.mEphemeris, SystemStatusEphemeris());
+ setDefaultIteminReport(mCache.mSvHealth, SystemStatusSvHealth());
+ setDefaultIteminReport(mCache.mPdr, SystemStatusPdr());
+ setDefaultIteminReport(mCache.mNavData, SystemStatusNavData());
+
+ setDefaultIteminReport(mCache.mPositionFailure, SystemStatusPositionFailure());
+
+ pthread_mutex_unlock(&mMutexSystemStatus);
+ return true;
+}
+
+/******************************************************************************
+@brief API to handle connection status update event from GnssRil
+
+@param[In] Connection status
+
+@return true when successfully done
+******************************************************************************/
+bool SystemStatus::eventConnectionStatus(bool connected, int8_t type,
+ bool roaming, NetworkHandle networkHandle,
+ string& apn)
+{
+ // send networkinof dataitem to systemstatus observer clients
+ SystemStatusNetworkInfo s(type, "", "", connected, roaming,
+ (uint64_t) networkHandle, apn);
+ mSysStatusObsvr.notify({&s});
+
+ return true;
+}
+
+/******************************************************************************
+@brief API to update power connect state
+
+@param[In] power connect status
+
+@return true when successfully done
+******************************************************************************/
+bool SystemStatus::updatePowerConnectState(bool charging)
+{
+ SystemStatusPowerConnectState s(charging);
+ mSysStatusObsvr.notify({&s});
+ return true;
+}
+} // namespace loc_core
+
diff --git a/gps/core/SystemStatus.h b/gps/core/SystemStatus.h
new file mode 100644
index 0000000..097e7cc
--- /dev/null
+++ b/gps/core/SystemStatus.h
@@ -0,0 +1,924 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __SYSTEM_STATUS__
+#define __SYSTEM_STATUS__
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <loc_pla.h>
+#include <log_util.h>
+#include <MsgTask.h>
+#include <IDataItemCore.h>
+#include <IOsObserver.h>
+#include <DataItemConcreteTypesBase.h>
+#include <SystemStatusOsObserver.h>
+
+#include <gps_extended_c.h>
+
+#define GPS_MIN (1) //1-32
+#define SBAS_MIN (33)
+#define GLO_MIN (65) //65-88
+#define QZSS_MIN (193) //193-197
+#define BDS_MIN (201) //201-237
+#define GAL_MIN (301) //301-336
+#define NAVIC_MIN (401) //401-414
+
+#define GPS_NUM (32)
+#define SBAS_NUM (32)
+#define GLO_NUM (24)
+#define QZSS_NUM (5)
+#define BDS_NUM (37)
+#define GAL_NUM (36)
+#define NAVIC_NUM (14)
+#define SV_ALL_NUM_MIN (GPS_NUM + GLO_NUM + QZSS_NUM + BDS_NUM + GAL_NUM) //=134
+#define SV_ALL_NUM (SV_ALL_NUM_MIN + NAVIC_NUM) //=148
+
+namespace loc_core
+{
+
+/******************************************************************************
+ SystemStatus report data structure
+******************************************************************************/
+class SystemStatusItemBase
+{
+public:
+ timespec mUtcTime;
+ timespec mUtcReported;
+ static const uint32_t maxItem = 5;
+
+ SystemStatusItemBase() {
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ mUtcTime.tv_sec = tv.tv_sec;
+ mUtcTime.tv_nsec = tv.tv_usec*1000ULL;
+ mUtcReported = mUtcTime;
+ };
+ virtual ~SystemStatusItemBase() {};
+ inline virtual SystemStatusItemBase& collate(SystemStatusItemBase&) {
+ return *this;
+ }
+ virtual void dump(void) {};
+ inline virtual bool ignore() { return false; };
+};
+
+class SystemStatusLocation : public SystemStatusItemBase
+{
+public:
+ bool mValid;
+ UlpLocation mLocation;
+ GpsLocationExtended mLocationEx;
+ inline SystemStatusLocation() :
+ mValid(false) {}
+ inline SystemStatusLocation(const UlpLocation& location,
+ const GpsLocationExtended& locationEx) :
+ mValid(true),
+ mLocation(location),
+ mLocationEx(locationEx) {}
+ bool equals(const SystemStatusLocation& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWM1;
+class SystemStatusTimeAndClock : public SystemStatusItemBase
+{
+public:
+ uint16_t mGpsWeek;
+ uint32_t mGpsTowMs;
+ uint8_t mTimeValid;
+ uint8_t mTimeSource;
+ int32_t mTimeUnc;
+ int32_t mClockFreqBias;
+ int32_t mClockFreqBiasUnc;
+ int32_t mLeapSeconds;
+ int32_t mLeapSecUnc;
+ uint64_t mTimeUncNs;
+ inline SystemStatusTimeAndClock() :
+ mGpsWeek(0),
+ mGpsTowMs(0),
+ mTimeValid(0),
+ mTimeSource(0),
+ mTimeUnc(0),
+ mClockFreqBias(0),
+ mClockFreqBiasUnc(0),
+ mLeapSeconds(0),
+ mLeapSecUnc(0),
+ mTimeUncNs(0ULL) {}
+ inline SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea);
+ bool equals(const SystemStatusTimeAndClock& peer);
+ void dump(void) override;
+};
+
+class SystemStatusXoState : public SystemStatusItemBase
+{
+public:
+ uint8_t mXoState;
+ inline SystemStatusXoState() :
+ mXoState(0) {}
+ inline SystemStatusXoState(const SystemStatusPQWM1& nmea);
+ bool equals(const SystemStatusXoState& peer);
+ void dump(void) override;
+};
+
+class SystemStatusRfAndParams : public SystemStatusItemBase
+{
+public:
+ int32_t mPgaGain;
+ uint32_t mGpsBpAmpI;
+ uint32_t mGpsBpAmpQ;
+ uint32_t mAdcI;
+ uint32_t mAdcQ;
+ uint32_t mJammerGps;
+ uint32_t mJammerGlo;
+ uint32_t mJammerBds;
+ uint32_t mJammerGal;
+ double mAgcGps;
+ double mAgcGlo;
+ double mAgcBds;
+ double mAgcGal;
+ uint32_t mGloBpAmpI;
+ uint32_t mGloBpAmpQ;
+ uint32_t mBdsBpAmpI;
+ uint32_t mBdsBpAmpQ;
+ uint32_t mGalBpAmpI;
+ uint32_t mGalBpAmpQ;
+ inline SystemStatusRfAndParams() :
+ mPgaGain(0),
+ mGpsBpAmpI(0),
+ mGpsBpAmpQ(0),
+ mAdcI(0),
+ mAdcQ(0),
+ mJammerGps(0),
+ mJammerGlo(0),
+ mJammerBds(0),
+ mJammerGal(0),
+ mAgcGps(0),
+ mAgcGlo(0),
+ mAgcBds(0),
+ mAgcGal(0),
+ mGloBpAmpI(0),
+ mGloBpAmpQ(0),
+ mBdsBpAmpI(0),
+ mBdsBpAmpQ(0),
+ mGalBpAmpI(0),
+ mGalBpAmpQ(0) {}
+ inline SystemStatusRfAndParams(const SystemStatusPQWM1& nmea);
+ bool equals(const SystemStatusRfAndParams& peer);
+ void dump(void) override;
+};
+
+class SystemStatusErrRecovery : public SystemStatusItemBase
+{
+public:
+ uint32_t mRecErrorRecovery;
+ inline SystemStatusErrRecovery() :
+ mRecErrorRecovery(0) {};
+ inline SystemStatusErrRecovery(const SystemStatusPQWM1& nmea);
+ bool equals(const SystemStatusErrRecovery& peer);
+ inline bool ignore() override { return 0 == mRecErrorRecovery; };
+ void dump(void) override;
+};
+
+class SystemStatusPQWP1;
+class SystemStatusInjectedPosition : public SystemStatusItemBase
+{
+public:
+ uint8_t mEpiValidity;
+ float mEpiLat;
+ float mEpiLon;
+ float mEpiAlt;
+ float mEpiHepe;
+ float mEpiAltUnc;
+ uint8_t mEpiSrc;
+ inline SystemStatusInjectedPosition() :
+ mEpiValidity(0),
+ mEpiLat(0),
+ mEpiLon(0),
+ mEpiAlt(0),
+ mEpiHepe(0),
+ mEpiAltUnc(0),
+ mEpiSrc(0) {}
+ inline SystemStatusInjectedPosition(const SystemStatusPQWP1& nmea);
+ bool equals(const SystemStatusInjectedPosition& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP2;
+class SystemStatusBestPosition : public SystemStatusItemBase
+{
+public:
+ bool mValid;
+ float mBestLat;
+ float mBestLon;
+ float mBestAlt;
+ float mBestHepe;
+ float mBestAltUnc;
+ inline SystemStatusBestPosition() :
+ mValid(false),
+ mBestLat(0),
+ mBestLon(0),
+ mBestAlt(0),
+ mBestHepe(0),
+ mBestAltUnc(0) {}
+ inline SystemStatusBestPosition(const SystemStatusPQWP2& nmea);
+ bool equals(const SystemStatusBestPosition& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP3;
+class SystemStatusXtra : public SystemStatusItemBase
+{
+public:
+ uint8_t mXtraValidMask;
+ uint32_t mGpsXtraAge;
+ uint32_t mGloXtraAge;
+ uint32_t mBdsXtraAge;
+ uint32_t mGalXtraAge;
+ uint32_t mQzssXtraAge;
+ uint32_t mNavicXtraAge;
+ uint32_t mGpsXtraValid;
+ uint32_t mGloXtraValid;
+ uint64_t mBdsXtraValid;
+ uint64_t mGalXtraValid;
+ uint8_t mQzssXtraValid;
+ uint32_t mNavicXtraValid;
+ inline SystemStatusXtra() :
+ mXtraValidMask(0),
+ mGpsXtraAge(0),
+ mGloXtraAge(0),
+ mBdsXtraAge(0),
+ mGalXtraAge(0),
+ mQzssXtraAge(0),
+ mNavicXtraAge(0),
+ mGpsXtraValid(0),
+ mGloXtraValid(0),
+ mBdsXtraValid(0ULL),
+ mGalXtraValid(0ULL),
+ mQzssXtraValid(0),
+ mNavicXtraValid(0) {}
+ inline SystemStatusXtra(const SystemStatusPQWP3& nmea);
+ bool equals(const SystemStatusXtra& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP4;
+class SystemStatusEphemeris : public SystemStatusItemBase
+{
+public:
+ uint32_t mGpsEpheValid;
+ uint32_t mGloEpheValid;
+ uint64_t mBdsEpheValid;
+ uint64_t mGalEpheValid;
+ uint8_t mQzssEpheValid;
+ inline SystemStatusEphemeris() :
+ mGpsEpheValid(0),
+ mGloEpheValid(0),
+ mBdsEpheValid(0ULL),
+ mGalEpheValid(0ULL),
+ mQzssEpheValid(0) {}
+ inline SystemStatusEphemeris(const SystemStatusPQWP4& nmea);
+ bool equals(const SystemStatusEphemeris& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP5;
+class SystemStatusSvHealth : public SystemStatusItemBase
+{
+public:
+ uint32_t mGpsUnknownMask;
+ uint32_t mGloUnknownMask;
+ uint64_t mBdsUnknownMask;
+ uint64_t mGalUnknownMask;
+ uint8_t mQzssUnknownMask;
+ uint32_t mNavicUnknownMask;
+ uint32_t mGpsGoodMask;
+ uint32_t mGloGoodMask;
+ uint64_t mBdsGoodMask;
+ uint64_t mGalGoodMask;
+ uint8_t mQzssGoodMask;
+ uint32_t mNavicGoodMask;
+ uint32_t mGpsBadMask;
+ uint32_t mGloBadMask;
+ uint64_t mBdsBadMask;
+ uint64_t mGalBadMask;
+ uint8_t mQzssBadMask;
+ uint32_t mNavicBadMask;
+ inline SystemStatusSvHealth() :
+ mGpsUnknownMask(0),
+ mGloUnknownMask(0),
+ mBdsUnknownMask(0ULL),
+ mGalUnknownMask(0ULL),
+ mQzssUnknownMask(0),
+ mNavicUnknownMask(0),
+ mGpsGoodMask(0),
+ mGloGoodMask(0),
+ mBdsGoodMask(0ULL),
+ mGalGoodMask(0ULL),
+ mQzssGoodMask(0),
+ mNavicGoodMask(0),
+ mGpsBadMask(0),
+ mGloBadMask(0),
+ mBdsBadMask(0ULL),
+ mGalBadMask(0ULL),
+ mQzssBadMask(0),
+ mNavicBadMask(0) {}
+ inline SystemStatusSvHealth(const SystemStatusPQWP5& nmea);
+ bool equals(const SystemStatusSvHealth& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP6;
+class SystemStatusPdr : public SystemStatusItemBase
+{
+public:
+ uint32_t mFixInfoMask;
+ inline SystemStatusPdr() :
+ mFixInfoMask(0) {}
+ inline SystemStatusPdr(const SystemStatusPQWP6& nmea);
+ bool equals(const SystemStatusPdr& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWP7;
+struct SystemStatusNav
+{
+ GnssEphemerisType mType;
+ GnssEphemerisSource mSource;
+ int32_t mAgeSec;
+};
+
+class SystemStatusNavData : public SystemStatusItemBase
+{
+public:
+ SystemStatusNav mNav[SV_ALL_NUM];
+ inline SystemStatusNavData() {
+ for (uint32_t i=0; i<SV_ALL_NUM; i++) {
+ mNav[i].mType = GNSS_EPH_TYPE_UNKNOWN;
+ mNav[i].mSource = GNSS_EPH_SOURCE_UNKNOWN;
+ mNav[i].mAgeSec = 0;
+ }
+ }
+ inline SystemStatusNavData(const SystemStatusPQWP7& nmea);
+ bool equals(const SystemStatusNavData& peer);
+ void dump(void) override;
+};
+
+class SystemStatusPQWS1;
+class SystemStatusPositionFailure : public SystemStatusItemBase
+{
+public:
+ uint32_t mFixInfoMask;
+ uint32_t mHepeLimit;
+ inline SystemStatusPositionFailure() :
+ mFixInfoMask(0),
+ mHepeLimit(0) {}
+ inline SystemStatusPositionFailure(const SystemStatusPQWS1& nmea);
+ bool equals(const SystemStatusPositionFailure& peer);
+ void dump(void) override;
+};
+
+/******************************************************************************
+ SystemStatus report data structure - from DataItem observer
+******************************************************************************/
+class SystemStatusAirplaneMode : public SystemStatusItemBase,
+ public AirplaneModeDataItemBase
+{
+public:
+ inline SystemStatusAirplaneMode(bool mode=false) :
+ AirplaneModeDataItemBase(mode) {}
+ inline SystemStatusAirplaneMode(const AirplaneModeDataItemBase& itemBase) :
+ AirplaneModeDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusAirplaneMode& peer) {
+ return (mMode == peer.mMode);
+ }
+};
+
+class SystemStatusENH : public SystemStatusItemBase,
+ public ENHDataItemBase
+{
+public:
+ inline SystemStatusENH(bool enabled=false) :
+ ENHDataItemBase(enabled) {}
+ inline SystemStatusENH(const ENHDataItemBase& itemBase) :
+ ENHDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusENH& peer) {
+ return (mEnabled == peer.mEnabled);
+ }
+};
+
+class SystemStatusGpsState : public SystemStatusItemBase,
+ public GPSStateDataItemBase
+{
+public:
+ inline SystemStatusGpsState(bool enabled=false) :
+ GPSStateDataItemBase(enabled) {}
+ inline SystemStatusGpsState(const GPSStateDataItemBase& itemBase) :
+ GPSStateDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusGpsState& peer) {
+ return (mEnabled == peer.mEnabled);
+ }
+ inline void dump(void) override {
+ LOC_LOGD("GpsState: state=%u", mEnabled);
+ }
+};
+
+class SystemStatusNLPStatus : public SystemStatusItemBase,
+ public NLPStatusDataItemBase
+{
+public:
+ inline SystemStatusNLPStatus(bool enabled=false) :
+ NLPStatusDataItemBase(enabled) {}
+ inline SystemStatusNLPStatus(const NLPStatusDataItemBase& itemBase) :
+ NLPStatusDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusNLPStatus& peer) {
+ return (mEnabled == peer.mEnabled);
+ }
+};
+
+class SystemStatusWifiHardwareState : public SystemStatusItemBase,
+ public WifiHardwareStateDataItemBase
+{
+public:
+ inline SystemStatusWifiHardwareState(bool enabled=false) :
+ WifiHardwareStateDataItemBase(enabled) {}
+ inline SystemStatusWifiHardwareState(const WifiHardwareStateDataItemBase& itemBase) :
+ WifiHardwareStateDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusWifiHardwareState& peer) {
+ return (mEnabled == peer.mEnabled);
+ }
+};
+
+class SystemStatusNetworkInfo : public SystemStatusItemBase,
+ public NetworkInfoDataItemBase
+{
+ NetworkInfoDataItemBase* mSrcObjPtr;
+public:
+ inline SystemStatusNetworkInfo(
+ int32_t type = 0,
+ std::string typeName = "",
+ string subTypeName = "",
+ bool connected = false,
+ bool roaming = false,
+ uint64_t networkHandle = NETWORK_HANDLE_UNKNOWN,
+ string apn = "") :
+ NetworkInfoDataItemBase(
+ (NetworkType)type,
+ type,
+ typeName,
+ subTypeName,
+ connected && (!roaming),
+ connected,
+ roaming,
+ networkHandle, apn),
+ mSrcObjPtr(nullptr) {}
+ inline SystemStatusNetworkInfo(const NetworkInfoDataItemBase& itemBase) :
+ NetworkInfoDataItemBase(itemBase),
+ mSrcObjPtr((NetworkInfoDataItemBase*)&itemBase) {
+ mType = (int32_t)itemBase.getType();
+ }
+ inline bool equals(const SystemStatusNetworkInfo& peer) {
+ bool rtv = (peer.mConnected == mConnected);
+ for (uint8_t i = 0; rtv && i < MAX_NETWORK_HANDLES; ++i) {
+ rtv &= (mAllNetworkHandles[i] == peer.mAllNetworkHandles[i]);
+ }
+ return peer.mApn.compare(mApn);
+ }
+ inline virtual SystemStatusItemBase& collate(SystemStatusItemBase& curInfo) {
+ uint64_t allTypes = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mAllTypes;
+ string& apn = (static_cast<SystemStatusNetworkInfo&>(curInfo)).mApn;
+ // Replace current with cached table for now and then update
+ memcpy(mAllNetworkHandles,
+ (static_cast<SystemStatusNetworkInfo&>(curInfo)).getNetworkHandle(),
+ sizeof(mAllNetworkHandles));
+ // Update the apn for non-mobile type connections.
+ if (TYPE_MOBILE != mType && apn.compare("") != 0) {
+ mApn = apn;
+ }
+ if (mConnected) {
+ mAllTypes |= allTypes;
+ for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
+ if (mNetworkHandle == mAllNetworkHandles[i].networkHandle) {
+ LOC_LOGD("collate duplicate detected, not updating");
+ break;
+ }
+ if (NETWORK_HANDLE_UNKNOWN == mAllNetworkHandles[i].networkHandle) {
+ mAllNetworkHandles[i].networkHandle = mNetworkHandle;
+ mAllNetworkHandles[i].networkType = (loc_core::NetworkType) mType;
+ break;
+ }
+ }
+ } else if (0 != mAllTypes) {
+ uint8_t deletedIndex = MAX_NETWORK_HANDLES;
+ uint8_t lastValidIndex = 0;
+ uint8_t typeCount = 0;
+ for (; lastValidIndex < MAX_NETWORK_HANDLES &&
+ NETWORK_HANDLE_UNKNOWN != mAllNetworkHandles[lastValidIndex].networkHandle;
+ ++lastValidIndex) {
+ // Maintain count for number of network handles still
+ // connected for given type
+ if (mType == (int32_t)mAllNetworkHandles[lastValidIndex].networkType) {
+ if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) {
+ deletedIndex = lastValidIndex;
+ } else {
+ typeCount++;
+ }
+ }
+
+ }
+ if (lastValidIndex > 0) {
+ --lastValidIndex;
+ }
+
+ if (MAX_NETWORK_HANDLES != deletedIndex) {
+ LOC_LOGd("deletedIndex:%u, lastValidIndex:%u, typeCount:%u",
+ deletedIndex, lastValidIndex, typeCount);
+ mAllNetworkHandles[deletedIndex] = mAllNetworkHandles[lastValidIndex];
+ mAllNetworkHandles[lastValidIndex].networkHandle = NETWORK_HANDLE_UNKNOWN;
+ mAllNetworkHandles[lastValidIndex].networkType = TYPE_UNKNOWN;
+ }
+
+ // If no more handles of given type, set bitmask
+ if (0 == typeCount) {
+ mAllTypes = (allTypes & (~mAllTypes));
+ LOC_LOGD("mAllTypes:%" PRIx64, mAllTypes);
+ }
+ } // else (mConnected == false && mAllTypes == 0)
+ // we keep mAllTypes as 0, which means no more connections.
+
+ if (nullptr != mSrcObjPtr) {
+ // this is critical, changing mAllTypes of the original obj
+ mSrcObjPtr->mAllTypes = mAllTypes;
+ memcpy(mSrcObjPtr->mAllNetworkHandles,
+ mAllNetworkHandles,
+ sizeof(mSrcObjPtr->mAllNetworkHandles));
+ }
+ return *this;
+ }
+ inline void dump(void) override {
+ LOC_LOGD("NetworkInfo: mAllTypes=%" PRIx64 " connected=%u mType=%x mApn=%s",
+ mAllTypes, mConnected, mType, mApn.c_str());
+ }
+};
+
+class SystemStatusServiceInfo : public SystemStatusItemBase,
+ public RilServiceInfoDataItemBase
+{
+public:
+ inline SystemStatusServiceInfo() :
+ RilServiceInfoDataItemBase() {}
+ inline SystemStatusServiceInfo(const RilServiceInfoDataItemBase& itemBase) :
+ RilServiceInfoDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusServiceInfo& peer) {
+ return static_cast<const RilServiceInfoDataItemBase&>(peer) ==
+ static_cast<const RilServiceInfoDataItemBase&>(*this);
+ }
+};
+
+class SystemStatusRilCellInfo : public SystemStatusItemBase,
+ public RilCellInfoDataItemBase
+{
+public:
+ inline SystemStatusRilCellInfo() :
+ RilCellInfoDataItemBase() {}
+ inline SystemStatusRilCellInfo(const RilCellInfoDataItemBase& itemBase) :
+ RilCellInfoDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusRilCellInfo& peer) {
+ return static_cast<const RilCellInfoDataItemBase&>(peer) ==
+ static_cast<const RilCellInfoDataItemBase&>(*this);
+ }
+};
+
+class SystemStatusServiceStatus : public SystemStatusItemBase,
+ public ServiceStatusDataItemBase
+{
+public:
+ inline SystemStatusServiceStatus(int32_t mServiceState=0) :
+ ServiceStatusDataItemBase(mServiceState) {}
+ inline SystemStatusServiceStatus(const ServiceStatusDataItemBase& itemBase) :
+ ServiceStatusDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusServiceStatus& peer) {
+ return (mServiceState == peer.mServiceState);
+ }
+};
+
+class SystemStatusModel : public SystemStatusItemBase,
+ public ModelDataItemBase
+{
+public:
+ inline SystemStatusModel(string name="") :
+ ModelDataItemBase(name) {}
+ inline SystemStatusModel(const ModelDataItemBase& itemBase) :
+ ModelDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusModel& peer) {
+ return (mModel == peer.mModel);
+ }
+};
+
+class SystemStatusManufacturer : public SystemStatusItemBase,
+ public ManufacturerDataItemBase
+{
+public:
+ inline SystemStatusManufacturer(string name="") :
+ ManufacturerDataItemBase(name) {}
+ inline SystemStatusManufacturer(const ManufacturerDataItemBase& itemBase) :
+ ManufacturerDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusManufacturer& peer) {
+ return (mManufacturer == peer.mManufacturer);
+ }
+};
+
+class SystemStatusAssistedGps : public SystemStatusItemBase,
+ public AssistedGpsDataItemBase
+{
+public:
+ inline SystemStatusAssistedGps(bool enabled=false) :
+ AssistedGpsDataItemBase(enabled) {}
+ inline SystemStatusAssistedGps(const AssistedGpsDataItemBase& itemBase) :
+ AssistedGpsDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusAssistedGps& peer) {
+ return (mEnabled == peer.mEnabled);
+ }
+};
+
+class SystemStatusScreenState : public SystemStatusItemBase,
+ public ScreenStateDataItemBase
+{
+public:
+ inline SystemStatusScreenState(bool state=false) :
+ ScreenStateDataItemBase(state) {}
+ inline SystemStatusScreenState(const ScreenStateDataItemBase& itemBase) :
+ ScreenStateDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusScreenState& peer) {
+ return (mState == peer.mState);
+ }
+};
+
+class SystemStatusPowerConnectState : public SystemStatusItemBase,
+ public PowerConnectStateDataItemBase
+{
+public:
+ inline SystemStatusPowerConnectState(bool state=false) :
+ PowerConnectStateDataItemBase(state) {}
+ inline SystemStatusPowerConnectState(const PowerConnectStateDataItemBase& itemBase) :
+ PowerConnectStateDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusPowerConnectState& peer) {
+ return (mState == peer.mState);
+ }
+};
+
+class SystemStatusTimeZoneChange : public SystemStatusItemBase,
+ public TimeZoneChangeDataItemBase
+{
+public:
+ inline SystemStatusTimeZoneChange(
+ int64_t currTimeMillis=0ULL, int32_t rawOffset=0, int32_t dstOffset=0) :
+ TimeZoneChangeDataItemBase(currTimeMillis, rawOffset, dstOffset) {}
+ inline SystemStatusTimeZoneChange(const TimeZoneChangeDataItemBase& itemBase) :
+ TimeZoneChangeDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusTimeZoneChange& peer) {
+ return ((mCurrTimeMillis == peer.mCurrTimeMillis) &&
+ (mRawOffsetTZ == peer.mRawOffsetTZ) &&
+ (mDstOffsetTZ == peer.mDstOffsetTZ));
+ }
+};
+
+class SystemStatusTimeChange : public SystemStatusItemBase,
+ public TimeChangeDataItemBase
+{
+public:
+ inline SystemStatusTimeChange(
+ int64_t currTimeMillis=0ULL, int32_t rawOffset=0, int32_t dstOffset=0) :
+ TimeChangeDataItemBase(currTimeMillis, rawOffset, dstOffset) {}
+ inline SystemStatusTimeChange(const TimeChangeDataItemBase& itemBase) :
+ TimeChangeDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusTimeChange& peer) {
+ return ((mCurrTimeMillis == peer.mCurrTimeMillis) &&
+ (mRawOffsetTZ == peer.mRawOffsetTZ) &&
+ (mDstOffsetTZ == peer.mDstOffsetTZ));
+ }
+};
+
+class SystemStatusWifiSupplicantStatus : public SystemStatusItemBase,
+ public WifiSupplicantStatusDataItemBase
+{
+public:
+ inline SystemStatusWifiSupplicantStatus() :
+ WifiSupplicantStatusDataItemBase() {}
+ inline SystemStatusWifiSupplicantStatus(const WifiSupplicantStatusDataItemBase& itemBase) :
+ WifiSupplicantStatusDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusWifiSupplicantStatus& peer) {
+ return ((mState == peer.mState) &&
+ (mApMacAddressValid == peer.mApMacAddressValid) &&
+ (mWifiApSsidValid == peer.mWifiApSsidValid) &&
+ (mWifiApSsid == peer.mWifiApSsid));
+ }
+};
+
+class SystemStatusShutdownState : public SystemStatusItemBase,
+ public ShutdownStateDataItemBase
+{
+public:
+ inline SystemStatusShutdownState(bool state=false) :
+ ShutdownStateDataItemBase(state) {}
+ inline SystemStatusShutdownState(const ShutdownStateDataItemBase& itemBase) :
+ ShutdownStateDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusShutdownState& peer) {
+ return (mState == peer.mState);
+ }
+};
+
+class SystemStatusTac : public SystemStatusItemBase,
+ public TacDataItemBase
+{
+public:
+ inline SystemStatusTac(std::string value="") :
+ TacDataItemBase(value) {}
+ inline SystemStatusTac(const TacDataItemBase& itemBase) :
+ TacDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusTac& peer) {
+ return (mValue == peer.mValue);
+ }
+ inline void dump(void) override {
+ LOC_LOGD("Tac: value=%s", mValue.c_str());
+ }
+};
+
+class SystemStatusMccMnc : public SystemStatusItemBase,
+ public MccmncDataItemBase
+{
+public:
+ inline SystemStatusMccMnc(std::string value="") :
+ MccmncDataItemBase(value) {}
+ inline SystemStatusMccMnc(const MccmncDataItemBase& itemBase) :
+ MccmncDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusMccMnc& peer) {
+ return (mValue == peer.mValue);
+ }
+ inline void dump(void) override {
+ LOC_LOGD("TacMccMnc value=%s", mValue.c_str());
+ }
+};
+
+class SystemStatusBtDeviceScanDetail : public SystemStatusItemBase,
+ public BtDeviceScanDetailsDataItemBase
+{
+public:
+ inline SystemStatusBtDeviceScanDetail() :
+ BtDeviceScanDetailsDataItemBase() {}
+ inline SystemStatusBtDeviceScanDetail(const BtDeviceScanDetailsDataItemBase& itemBase) :
+ BtDeviceScanDetailsDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusBtDeviceScanDetail& peer) {
+ return ((mApSrnRssi == peer.mApSrnRssi) &&
+ (0 == memcmp(mApSrnMacAddress, peer.mApSrnMacAddress, sizeof(mApSrnMacAddress))) &&
+ (mApSrnTimestamp == peer.mApSrnTimestamp) &&
+ (mRequestTimestamp == peer.mRequestTimestamp) &&
+ (mReceiveTimestamp == peer.mReceiveTimestamp));
+ }
+};
+
+class SystemStatusBtleDeviceScanDetail : public SystemStatusItemBase,
+ public BtLeDeviceScanDetailsDataItemBase
+{
+public:
+ inline SystemStatusBtleDeviceScanDetail() :
+ BtLeDeviceScanDetailsDataItemBase() {}
+ inline SystemStatusBtleDeviceScanDetail(const BtLeDeviceScanDetailsDataItemBase& itemBase) :
+ BtLeDeviceScanDetailsDataItemBase(itemBase) {}
+ inline bool equals(const SystemStatusBtleDeviceScanDetail& peer) {
+ return ((mApSrnRssi == peer.mApSrnRssi) &&
+ (0 == memcmp(mApSrnMacAddress, peer.mApSrnMacAddress, sizeof(mApSrnMacAddress))) &&
+ (mApSrnTimestamp == peer.mApSrnTimestamp) &&
+ (mRequestTimestamp == peer.mRequestTimestamp) &&
+ (mReceiveTimestamp == peer.mReceiveTimestamp));
+ }
+};
+
+/******************************************************************************
+ SystemStatusReports
+******************************************************************************/
+class SystemStatusReports
+{
+public:
+ // from QMI_LOC indication
+ std::vector<SystemStatusLocation> mLocation;
+
+ // from ME debug NMEA
+ std::vector<SystemStatusTimeAndClock> mTimeAndClock;
+ std::vector<SystemStatusXoState> mXoState;
+ std::vector<SystemStatusRfAndParams> mRfAndParams;
+ std::vector<SystemStatusErrRecovery> mErrRecovery;
+
+ // from PE debug NMEA
+ std::vector<SystemStatusInjectedPosition> mInjectedPosition;
+ std::vector<SystemStatusBestPosition> mBestPosition;
+ std::vector<SystemStatusXtra> mXtra;
+ std::vector<SystemStatusEphemeris> mEphemeris;
+ std::vector<SystemStatusSvHealth> mSvHealth;
+ std::vector<SystemStatusPdr> mPdr;
+ std::vector<SystemStatusNavData> mNavData;
+
+ // from SM debug NMEA
+ std::vector<SystemStatusPositionFailure> mPositionFailure;
+
+ // from dataitems observer
+ std::vector<SystemStatusAirplaneMode> mAirplaneMode;
+ std::vector<SystemStatusENH> mENH;
+ std::vector<SystemStatusGpsState> mGPSState;
+ std::vector<SystemStatusNLPStatus> mNLPStatus;
+ std::vector<SystemStatusWifiHardwareState> mWifiHardwareState;
+ std::vector<SystemStatusNetworkInfo> mNetworkInfo;
+ std::vector<SystemStatusServiceInfo> mRilServiceInfo;
+ std::vector<SystemStatusRilCellInfo> mRilCellInfo;
+ std::vector<SystemStatusServiceStatus> mServiceStatus;
+ std::vector<SystemStatusModel> mModel;
+ std::vector<SystemStatusManufacturer> mManufacturer;
+ std::vector<SystemStatusAssistedGps> mAssistedGps;
+ std::vector<SystemStatusScreenState> mScreenState;
+ std::vector<SystemStatusPowerConnectState> mPowerConnectState;
+ std::vector<SystemStatusTimeZoneChange> mTimeZoneChange;
+ std::vector<SystemStatusTimeChange> mTimeChange;
+ std::vector<SystemStatusWifiSupplicantStatus> mWifiSupplicantStatus;
+ std::vector<SystemStatusShutdownState> mShutdownState;
+ std::vector<SystemStatusTac> mTac;
+ std::vector<SystemStatusMccMnc> mMccMnc;
+ std::vector<SystemStatusBtDeviceScanDetail> mBtDeviceScanDetail;
+ std::vector<SystemStatusBtleDeviceScanDetail> mBtLeDeviceScanDetail;
+};
+
+/******************************************************************************
+ SystemStatus
+******************************************************************************/
+class SystemStatus
+{
+private:
+ static SystemStatus *mInstance;
+ SystemStatusOsObserver mSysStatusObsvr;
+ // ctor
+ SystemStatus(const MsgTask* msgTask);
+ // dtor
+ inline ~SystemStatus() {}
+
+ // Data members
+ static pthread_mutex_t mMutexSystemStatus;
+ SystemStatusReports mCache;
+
+ template <typename TYPE_REPORT, typename TYPE_ITEM>
+ bool setIteminReport(TYPE_REPORT& report, TYPE_ITEM&& s);
+
+ // set default dataitem derived item in report cache
+ template <typename TYPE_REPORT, typename TYPE_ITEM>
+ void setDefaultIteminReport(TYPE_REPORT& report, const TYPE_ITEM& s);
+
+ template <typename TYPE_REPORT, typename TYPE_ITEM>
+ void getIteminReport(TYPE_REPORT& reportout, const TYPE_ITEM& c) const;
+
+public:
+ // Static methods
+ static SystemStatus* getInstance(const MsgTask* msgTask);
+ static void destroyInstance();
+ IOsObserver* getOsObserver();
+
+ // Helpers
+ bool eventPosition(const UlpLocation& location,const GpsLocationExtended& locationEx);
+ bool eventDataItemNotify(IDataItemCore* dataitem);
+ bool setNmeaString(const char *data, uint32_t len);
+ bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const;
+ bool setDefaultGnssEngineStates(void);
+ bool eventConnectionStatus(bool connected, int8_t type,
+ bool roaming, NetworkHandle networkHandle, string& apn);
+ bool updatePowerConnectState(bool charging);
+ void resetNetworkInfo();
+};
+
+} // namespace loc_core
+
+#endif //__SYSTEM_STATUS__
+
diff --git a/gps/core/SystemStatusOsObserver.cpp b/gps/core/SystemStatusOsObserver.cpp
new file mode 100644
index 0000000..8fd9564
--- /dev/null
+++ b/gps/core/SystemStatusOsObserver.cpp
@@ -0,0 +1,592 @@
+/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_SystemStatusOsObserver"
+
+#include <algorithm>
+#include <SystemStatus.h>
+#include <SystemStatusOsObserver.h>
+#include <IDataItemCore.h>
+#include <DataItemsFactoryProxy.h>
+
+namespace loc_core
+{
+template <typename CINT, typename COUT>
+COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
+ COUT outContainer = {};
+ for (auto item : inContainer) {
+ outContainer.insert(outContainer.begin(), item);
+ }
+ return outContainer;
+}
+
+SystemStatusOsObserver::~SystemStatusOsObserver() {
+ // Close data-item library handle
+ DataItemsFactoryProxy::closeDataItemLibraryHandle();
+
+ // Destroy cache
+ for (auto each : mDataItemCache) {
+ if (nullptr != each.second) {
+ delete each.second;
+ }
+ }
+
+ mDataItemCache.clear();
+}
+
+void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
+{
+ struct SetSubsObj : public LocMsg {
+ ObserverContext& mContext;
+ IDataItemSubscription* mSubsObj;
+ inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
+ mContext(context), mSubsObj(subscriptionObj) {}
+ void proc() const {
+ LOC_LOGi("SetSubsObj::enter");
+ mContext.mSubscriptionObj = mSubsObj;
+
+ if (!mContext.mSSObserver->mDataItemToClients.empty()) {
+ list<DataItemId> dis(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ mContext.mSSObserver->mDataItemToClients.getKeys()));
+ mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
+ mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
+ }
+ LOC_LOGi("SetSubsObj::exit");
+ }
+ };
+
+ if (nullptr == subscriptionObj) {
+ LOC_LOGw("subscriptionObj is NULL");
+ } else {
+ mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
+ }
+}
+
+/******************************************************************************
+ IDataItemSubscription Overrides
+******************************************************************************/
+void SystemStatusOsObserver::subscribe(const list<DataItemId>& l, IDataItemObserver* client,
+ bool toRequestData)
+{
+ struct HandleSubscribeReq : public LocMsg {
+ inline HandleSubscribeReq(SystemStatusOsObserver* parent,
+ list<DataItemId>& l, IDataItemObserver* client, bool requestData) :
+ mParent(parent), mClient(client),
+ mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)),
+ diItemlist(l),
+ mToRequestData(requestData) {}
+
+ void proc() const {
+ unordered_set<DataItemId> dataItemsToSubscribe = {};
+ mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
+ mParent->mClientToDataItems.add(mClient, mDataItemSet);
+
+ mParent->sendCachedDataItems(mDataItemSet, mClient);
+
+ // Send subscription set to framework
+ if (nullptr != mParent->mContext.mSubscriptionObj) {
+ if (mToRequestData) {
+ LOC_LOGD("Request Data sent to framework for the following");
+ mParent->mContext.mSubscriptionObj->requestData(diItemlist, mParent);
+ } else if (!dataItemsToSubscribe.empty()) {
+ LOC_LOGD("Subscribe Request sent to framework for the following");
+ mParent->logMe(dataItemsToSubscribe);
+ mParent->mContext.mSubscriptionObj->subscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToSubscribe)),
+ mParent);
+ }
+ }
+ }
+ mutable SystemStatusOsObserver* mParent;
+ IDataItemObserver* mClient;
+ const unordered_set<DataItemId> mDataItemSet;
+ const list<DataItemId> diItemlist;
+ bool mToRequestData;
+ };
+
+ if (l.empty() || nullptr == client) {
+ LOC_LOGw("Data item set is empty or client is nullptr");
+ } else {
+ mContext.mMsgTask->sendMsg(
+ new HandleSubscribeReq(this, (list<DataItemId>&)l, client, toRequestData));
+ }
+}
+
+void SystemStatusOsObserver::updateSubscription(
+ const list<DataItemId>& l, IDataItemObserver* client)
+{
+ struct HandleUpdateSubscriptionReq : public LocMsg {
+ HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
+ list<DataItemId>& l, IDataItemObserver* client) :
+ mParent(parent), mClient(client),
+ mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
+
+ void proc() const {
+ unordered_set<DataItemId> dataItemsToSubscribe = {};
+ unordered_set<DataItemId> dataItemsToUnsubscribe = {};
+ unordered_set<IDataItemObserver*> clients({mClient});
+ // below removes clients from all entries keyed with the return of the
+ // mClientToDataItems.update() call. If leaving an empty set of clients as the
+ // result, the entire entry will be removed. dataItemsToUnsubscribe will be
+ // populated to keep the keys of the removed entries.
+ mParent->mDataItemToClients.trimOrRemove(
+ // this call updates <IDataItemObserver*, DataItemId> map; removes
+ // the DataItemId's that are not new to the clietn from mDataItemSet;
+ // and returns a set of mDataItemSet's that are no longer used by client.
+ // This unused set of mDataItemSet's is passed to trimOrRemove method of
+ // <DataItemId, IDataItemObserver*> map to remove the client from the
+ // corresponding entries, and gets a set of the entries that are
+ // removed from the <DataItemId, IDataItemObserver*> map as a result.
+ mParent->mClientToDataItems.update(mClient,
+ (unordered_set<DataItemId>&)mDataItemSet),
+ clients, &dataItemsToUnsubscribe, nullptr);
+ // below adds mClient to <DataItemId, IDataItemObserver*> map, and populates
+ // new keys added to that map, which are DataItemIds to be subscribed.
+ mParent->mDataItemToClients.add(mDataItemSet, clients, &dataItemsToSubscribe);
+
+ // Send First Response
+ mParent->sendCachedDataItems(mDataItemSet, mClient);
+
+ if (nullptr != mParent->mContext.mSubscriptionObj) {
+ // Send subscription set to framework
+ if (!dataItemsToSubscribe.empty()) {
+ LOC_LOGD("Subscribe Request sent to framework for the following");
+ mParent->logMe(dataItemsToSubscribe);
+
+ mParent->mContext.mSubscriptionObj->subscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToSubscribe)),
+ mParent);
+ }
+
+ // Send unsubscribe to framework
+ if (!dataItemsToUnsubscribe.empty()) {
+ LOC_LOGD("Unsubscribe Request sent to framework for the following");
+ mParent->logMe(dataItemsToUnsubscribe);
+
+ mParent->mContext.mSubscriptionObj->unsubscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToUnsubscribe)),
+ mParent);
+ }
+ }
+ }
+ SystemStatusOsObserver* mParent;
+ IDataItemObserver* mClient;
+ unordered_set<DataItemId> mDataItemSet;
+ };
+
+ if (l.empty() || nullptr == client) {
+ LOC_LOGw("Data item set is empty or client is nullptr");
+ } else {
+ mContext.mMsgTask->sendMsg(
+ new HandleUpdateSubscriptionReq(this, (list<DataItemId>&)l, client));
+ }
+}
+
+void SystemStatusOsObserver::unsubscribe(
+ const list<DataItemId>& l, IDataItemObserver* client)
+{
+ struct HandleUnsubscribeReq : public LocMsg {
+ HandleUnsubscribeReq(SystemStatusOsObserver* parent,
+ list<DataItemId>& l, IDataItemObserver* client) :
+ mParent(parent), mClient(client),
+ mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
+
+ void proc() const {
+ unordered_set<DataItemId> dataItemsUnusedByClient = {};
+ unordered_set<IDataItemObserver*> clientToRemove = {};
+ unordered_set<DataItemId> dataItemsToUnsubscribe = {};
+ mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet, &clientToRemove,
+ &dataItemsUnusedByClient);
+ mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
+ &dataItemsToUnsubscribe, nullptr);
+
+ if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
+ LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
+ mParent->logMe(dataItemsToUnsubscribe);
+
+ // Send unsubscribe to framework
+ mParent->mContext.mSubscriptionObj->unsubscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToUnsubscribe)),
+ mParent);
+ }
+ }
+ SystemStatusOsObserver* mParent;
+ IDataItemObserver* mClient;
+ unordered_set<DataItemId> mDataItemSet;
+ };
+
+ if (l.empty() || nullptr == client) {
+ LOC_LOGw("Data item set is empty or client is nullptr");
+ } else {
+ mContext.mMsgTask->sendMsg(new HandleUnsubscribeReq(this, (list<DataItemId>&)l, client));
+ }
+}
+
+void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
+{
+ struct HandleUnsubscribeAllReq : public LocMsg {
+ HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
+ IDataItemObserver* client) :
+ mParent(parent), mClient(client) {}
+
+ void proc() const {
+ unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
+
+ if (!diByClient.empty()) {
+ unordered_set<DataItemId> dataItemsToUnsubscribe;
+ mParent->mClientToDataItems.remove(mClient);
+ mParent->mDataItemToClients.trimOrRemove(diByClient, {mClient},
+ &dataItemsToUnsubscribe, nullptr);
+
+ if (!dataItemsToUnsubscribe.empty() &&
+ nullptr != mParent->mContext.mSubscriptionObj) {
+
+ LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
+ mParent->logMe(dataItemsToUnsubscribe);
+
+ // Send unsubscribe to framework
+ mParent->mContext.mSubscriptionObj->unsubscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToUnsubscribe)),
+ mParent);
+ }
+ }
+ }
+ SystemStatusOsObserver* mParent;
+ IDataItemObserver* mClient;
+ };
+
+ if (nullptr == client) {
+ LOC_LOGw("Data item set is empty or client is nullptr");
+ } else {
+ mContext.mMsgTask->sendMsg(new HandleUnsubscribeAllReq(this, client));
+ }
+}
+
+/******************************************************************************
+ IDataItemObserver Overrides
+******************************************************************************/
+void SystemStatusOsObserver::notify(const list<IDataItemCore*>& dlist)
+{
+ struct HandleNotify : public LocMsg {
+ HandleNotify(SystemStatusOsObserver* parent, vector<IDataItemCore*>& v) :
+ mParent(parent), mDiVec(std::move(v)) {}
+
+ inline virtual ~HandleNotify() {
+ for (auto item : mDiVec) {
+ delete item;
+ }
+ }
+
+ void proc() const {
+ // Update Cache with received data items and prepare
+ // list of data items to be sent.
+ unordered_set<DataItemId> dataItemIdsToBeSent = {};
+ for (auto item : mDiVec) {
+ if (mParent->updateCache(item)) {
+ dataItemIdsToBeSent.insert(item->getId());
+ }
+ }
+
+ // Send data item to all subscribed clients
+ unordered_set<IDataItemObserver*> clientSet = {};
+ for (auto each : dataItemIdsToBeSent) {
+ auto clients = mParent->mDataItemToClients.getValSetPtr(each);
+ if (nullptr != clients) {
+ clientSet.insert(clients->begin(), clients->end());
+ }
+ }
+
+ for (auto client : clientSet) {
+ unordered_set<DataItemId> dataItemIdsForThisClient(
+ mParent->mClientToDataItems.getValSet(client));
+ for (auto itr = dataItemIdsForThisClient.begin();
+ itr != dataItemIdsForThisClient.end(); ) {
+ if (dataItemIdsToBeSent.find(*itr) == dataItemIdsToBeSent.end()) {
+ itr = dataItemIdsForThisClient.erase(itr);
+ } else {
+ itr++;
+ }
+ }
+
+ mParent->sendCachedDataItems(dataItemIdsForThisClient, client);
+ }
+ }
+ SystemStatusOsObserver* mParent;
+ const vector<IDataItemCore*> mDiVec;
+ };
+
+ if (!dlist.empty()) {
+ vector<IDataItemCore*> dataItemVec(dlist.size());
+
+ for (auto each : dlist) {
+
+ IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
+ if (nullptr == di) {
+ LOC_LOGw("Unable to create dataitem:%d", each->getId());
+ continue;
+ }
+
+ // Copy contents into the newly created data item
+ di->copy(each);
+
+ // add this dataitem if updated from last one
+ dataItemVec.push_back(di);
+ IF_LOC_LOGD {
+ string dv;
+ di->stringify(dv);
+ LOC_LOGd("notify: DataItem In Value:%s", dv.c_str());
+ }
+ }
+
+ if (!dataItemVec.empty()) {
+ mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
+ }
+ }
+}
+
+/******************************************************************************
+ IFrameworkActionReq Overrides
+******************************************************************************/
+void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
+{
+ if (nullptr == mContext.mFrameworkActionReqObj) {
+ LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
+ return;
+ }
+
+ // Check if data item exists in mActiveRequestCount
+ DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
+ if (citer == mActiveRequestCount.end()) {
+ // Data item not found in map
+ // Add reference count as 1 and add dataitem to map
+ pair<DataItemId, int> cpair(dit, 1);
+ mActiveRequestCount.insert(cpair);
+ LOC_LOGD("Sending turnOn request");
+
+ // Send action turn on to framework
+ struct HandleTurnOnMsg : public LocMsg {
+ HandleTurnOnMsg(IFrameworkActionReq* framework,
+ DataItemId dit, int timeOut) :
+ mFrameworkActionReqObj(framework), mDataItemId(dit), mTimeOut(timeOut) {}
+ virtual ~HandleTurnOnMsg() {}
+ void proc() const {
+ mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut);
+ }
+ IFrameworkActionReq* mFrameworkActionReqObj;
+ DataItemId mDataItemId;
+ int mTimeOut;
+ };
+ mContext.mMsgTask->sendMsg(
+ new (nothrow) HandleTurnOnMsg(mContext.mFrameworkActionReqObj, dit, timeOut));
+ }
+ else {
+ // Found in map, update reference count
+ citer->second++;
+ LOC_LOGD("turnOn - Data item:%d Num_refs:%d", dit, citer->second);
+ }
+}
+
+void SystemStatusOsObserver::turnOff(DataItemId dit)
+{
+ if (nullptr == mContext.mFrameworkActionReqObj) {
+ LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
+ return;
+ }
+
+ // Check if data item exists in mActiveRequestCount
+ DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
+ if (citer != mActiveRequestCount.end()) {
+ // found
+ citer->second--;
+ LOC_LOGD("turnOff - Data item:%d Remaining:%d", dit, citer->second);
+ if(citer->second == 0) {
+ // if this was last reference, remove item from map and turn off module
+ mActiveRequestCount.erase(citer);
+
+ // Send action turn off to framework
+ struct HandleTurnOffMsg : public LocMsg {
+ HandleTurnOffMsg(IFrameworkActionReq* framework, DataItemId dit) :
+ mFrameworkActionReqObj(framework), mDataItemId(dit) {}
+ virtual ~HandleTurnOffMsg() {}
+ void proc() const {
+ mFrameworkActionReqObj->turnOff(mDataItemId);
+ }
+ IFrameworkActionReq* mFrameworkActionReqObj;
+ DataItemId mDataItemId;
+ };
+ mContext.mMsgTask->sendMsg(
+ new (nothrow) HandleTurnOffMsg(mContext.mFrameworkActionReqObj, dit));
+ }
+ }
+}
+
+#ifdef USE_GLIB
+bool SystemStatusOsObserver::connectBackhaul(const string& clientName)
+{
+ bool result = false;
+
+ if (mContext.mFrameworkActionReqObj != NULL) {
+ struct HandleConnectBackhaul : public LocMsg {
+ HandleConnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
+ mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
+ virtual ~HandleConnectBackhaul() {}
+ void proc() const {
+ LOC_LOGi("HandleConnectBackhaul::enter");
+ mFwkActionReqObj->connectBackhaul(mClientName);
+ LOC_LOGi("HandleConnectBackhaul::exit");
+ }
+ IFrameworkActionReq* mFwkActionReqObj;
+ string mClientName;
+ };
+ mContext.mMsgTask->sendMsg(
+ new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj, clientName));
+ result = true;
+ }
+ else {
+ LOC_LOGe("Framework action request object is NULL.Caching connect request: %s",
+ clientName.c_str());
+ ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
+ if (iter == mBackHaulConnReqCache.end()) {
+ // not found in set. first time receiving from request from client
+ LOC_LOGe("Adding client to BackHaulConnReqCache list");
+ mBackHaulConnReqCache.insert(clientName);
+ }
+ result = false;
+ }
+ return result;
+
+}
+
+bool SystemStatusOsObserver::disconnectBackhaul(const string& clientName)
+{
+ bool result = false;
+
+ if (mContext.mFrameworkActionReqObj != NULL) {
+ struct HandleDisconnectBackhaul : public LocMsg {
+ HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
+ mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
+ virtual ~HandleDisconnectBackhaul() {}
+ void proc() const {
+ LOC_LOGi("HandleDisconnectBackhaul::enter");
+ mFwkActionReqObj->disconnectBackhaul(mClientName);
+ LOC_LOGi("HandleDisconnectBackhaul::exit");
+ }
+ IFrameworkActionReq* mFwkActionReqObj;
+ string mClientName;
+ };
+ mContext.mMsgTask->sendMsg(
+ new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj,
+ clientName));
+ }
+ else {
+ LOC_LOGe("Framework action request object is NULL.Caching disconnect request: %s",
+ clientName.c_str());
+ // Check if client has requested for backhaul connection.
+ ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
+ if (iter != mBackHaulConnReqCache.end()) {
+ // client found, remove from set.
+ LOC_LOGd("Removing client from BackHaulConnReqCache list");
+ mBackHaulConnReqCache.erase(iter);
+ }
+ result = false;
+ }
+ return result;
+}
+#endif
+/******************************************************************************
+ Helpers
+******************************************************************************/
+void SystemStatusOsObserver::sendCachedDataItems(
+ const unordered_set<DataItemId>& s, IDataItemObserver* to)
+{
+ if (nullptr == to) {
+ LOC_LOGv("client pointer is NULL.");
+ } else {
+ string clientName;
+ to->getName(clientName);
+ list<IDataItemCore*> dataItems = {};
+
+ for (auto each : s) {
+ auto citer = mDataItemCache.find(each);
+ if (citer != mDataItemCache.end()) {
+ string dv;
+ citer->second->stringify(dv);
+ LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
+ dataItems.push_front(citer->second);
+ }
+ }
+
+ if (dataItems.empty()) {
+ LOC_LOGv("No items to notify.");
+ } else {
+ to->notify(dataItems);
+ }
+ }
+}
+
+bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
+{
+ bool dataItemUpdated = false;
+
+ // Request systemstatus to record this dataitem in its cache
+ // if the return is false, it means that SystemStatus is not
+ // handling it, so SystemStatusOsObserver also doesn't.
+ // So it has to be true to proceed.
+ if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
+ auto citer = mDataItemCache.find(d->getId());
+ if (citer == mDataItemCache.end()) {
+ // New data item; not found in cache
+ IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
+ if (nullptr != dataitem) {
+ // Copy the contents of the data item
+ dataitem->copy(d);
+ // Insert in mDataItemCache
+ mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
+ dataItemUpdated = true;
+ }
+ } else {
+ // Found in cache; Update cache if necessary
+ citer->second->copy(d, &dataItemUpdated);
+ }
+
+ if (dataItemUpdated) {
+ LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
+ }
+ }
+
+ return dataItemUpdated;
+}
+
+} // namespace loc_core
+
diff --git a/gps/core/SystemStatusOsObserver.h b/gps/core/SystemStatusOsObserver.h
new file mode 100644
index 0000000..c0f56d8
--- /dev/null
+++ b/gps/core/SystemStatusOsObserver.h
@@ -0,0 +1,181 @@
+/* Copyright (c) 2015-2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __SYSTEM_STATUS_OSOBSERVER__
+#define __SYSTEM_STATUS_OSOBSERVER__
+
+#include <cinttypes>
+#include <string>
+#include <list>
+#include <map>
+#include <new>
+#include <vector>
+
+#include <MsgTask.h>
+#include <DataItemId.h>
+#include <IOsObserver.h>
+#include <loc_pla.h>
+#include <log_util.h>
+#include <LocUnorderedSetMap.h>
+
+namespace loc_core
+{
+/******************************************************************************
+ SystemStatusOsObserver
+******************************************************************************/
+using namespace std;
+using namespace loc_util;
+
+// Forward Declarations
+class IDataItemCore;
+class SystemStatus;
+class SystemStatusOsObserver;
+typedef map<IDataItemObserver*, list<DataItemId>> ObserverReqCache;
+typedef LocUnorderedSetMap<IDataItemObserver*, DataItemId> ClientToDataItems;
+typedef LocUnorderedSetMap<DataItemId, IDataItemObserver*> DataItemToClients;
+typedef unordered_map<DataItemId, IDataItemCore*> DataItemIdToCore;
+typedef unordered_map<DataItemId, int> DataItemIdToInt;
+#ifdef USE_GLIB
+// Cache details of backhaul client requests
+typedef unordered_set<string> ClientBackhaulReqCache;
+#endif
+
+struct ObserverContext {
+ IDataItemSubscription* mSubscriptionObj;
+ IFrameworkActionReq* mFrameworkActionReqObj;
+ const MsgTask* mMsgTask;
+ SystemStatusOsObserver* mSSObserver;
+
+ inline ObserverContext(const MsgTask* msgTask, SystemStatusOsObserver* observer) :
+ mSubscriptionObj(NULL), mFrameworkActionReqObj(NULL),
+ mMsgTask(msgTask), mSSObserver(observer) {}
+};
+
+// Clients wanting to get data from OS/Framework would need to
+// subscribe with OSObserver using IDataItemSubscription interface.
+// Such clients would need to implement IDataItemObserver interface
+// to receive data when it becomes available.
+class SystemStatusOsObserver : public IOsObserver {
+
+public:
+ // ctor
+ inline SystemStatusOsObserver(SystemStatus* systemstatus, const MsgTask* msgTask) :
+ mSystemStatus(systemstatus), mContext(msgTask, this),
+ mAddress("SystemStatusOsObserver"),
+ mClientToDataItems(MAX_DATA_ITEM_ID), mDataItemToClients(MAX_DATA_ITEM_ID) {}
+
+ // dtor
+ ~SystemStatusOsObserver();
+
+ template <typename CINT, typename COUT>
+ static COUT containerTransfer(CINT& s);
+ template <typename CINT, typename COUT>
+ inline static COUT containerTransfer(CINT&& s) {
+ return containerTransfer<CINT, COUT>(s);
+ }
+
+ // To set the subscription object
+ virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj);
+
+ // To set the framework action request object
+ inline void setFrameworkActionReqObj(IFrameworkActionReq* frameworkActionReqObj) {
+ mContext.mFrameworkActionReqObj = frameworkActionReqObj;
+#ifdef USE_GLIB
+ uint32_t numBackHaulClients = mBackHaulConnReqCache.size();
+ if (numBackHaulClients > 0) {
+ // For each client, invoke connectbackhaul.
+ for (auto clientName : mBackHaulConnReqCache) {
+ LOC_LOGd("Invoke connectBackhaul for client: %s", clientName.c_str());
+ connectBackhaul(clientName);
+ }
+ // Clear the set
+ mBackHaulConnReqCache.clear();
+ }
+#endif
+ }
+
+ // IDataItemSubscription Overrides
+ inline virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client) override {
+ subscribe(l, client, false);
+ }
+ virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client) override;
+ inline virtual void requestData(const list<DataItemId>& l, IDataItemObserver* client) override {
+ subscribe(l, client, true);
+ }
+ virtual void unsubscribe(const list<DataItemId>& l, IDataItemObserver* client) override;
+ virtual void unsubscribeAll(IDataItemObserver* client) override;
+
+ // IDataItemObserver Overrides
+ virtual void notify(const list<IDataItemCore*>& dlist) override;
+ inline virtual void getName(string& name) override {
+ name = mAddress;
+ }
+
+ // IFrameworkActionReq Overrides
+ virtual void turnOn(DataItemId dit, int timeOut = 0) override;
+ virtual void turnOff(DataItemId dit) override;
+#ifdef USE_GLIB
+ virtual bool connectBackhaul(const string& clientName) override;
+ virtual bool disconnectBackhaul(const string& clientName) override;
+#endif
+
+private:
+ SystemStatus* mSystemStatus;
+ ObserverContext mContext;
+ const string mAddress;
+ ClientToDataItems mClientToDataItems;
+ DataItemToClients mDataItemToClients;
+ DataItemIdToCore mDataItemCache;
+ DataItemIdToInt mActiveRequestCount;
+
+ // Cache the subscribe and requestData till subscription obj is obtained
+ void cacheObserverRequest(ObserverReqCache& reqCache,
+ const list<DataItemId>& l, IDataItemObserver* client);
+#ifdef USE_GLIB
+ // Cache the framework action request for connect/disconnect
+ ClientBackhaulReqCache mBackHaulConnReqCache;
+#endif
+
+ void subscribe(const list<DataItemId>& l, IDataItemObserver* client, bool toRequestData);
+
+ // Helpers
+ void sendCachedDataItems(const unordered_set<DataItemId>& s, IDataItemObserver* to);
+ bool updateCache(IDataItemCore* d);
+ inline void logMe(const unordered_set<DataItemId>& l) {
+ IF_LOC_LOGD {
+ for (auto id : l) {
+ LOC_LOGD("DataItem %d", id);
+ }
+ }
+ }
+};
+
+} // namespace loc_core
+
+#endif //__SYSTEM_STATUS__
+
diff --git a/gps/core/configure.ac b/gps/core/configure.ac
new file mode 100644
index 0000000..19db9cf
--- /dev/null
+++ b/gps/core/configure.ac
@@ -0,0 +1,107 @@
+# configure.ac -- Autoconf script for gps loc-core
+#
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the gps loc-hal package version 1.0.0
+AC_INIT([loc-core],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# Verifies the --srcdir is correct by checking for the path
+AC_CONFIG_SRCDIR([loc-core.pc.in])
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
+AC_SUBST([GPSUTILS_CFLAGS])
+AC_SUBST([GPSUTILS_LIBS])
+
+AC_ARG_WITH([core_includes],
+ AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+ [Specify the location of the core headers]),
+ [core_incdir=$withval],
+ with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x$with_locpla_includes" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_SUBST([CPPFLAGS])
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+AC_ARG_WITH([auto_feature],
+ AC_HELP_STRING([--with-auto_feature=@<:@dir@:>@],
+ [Using Automotive feature]),
+ [],
+ with_auto_feature=no)
+
+if test "x$with_auto_feature" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -DFEATURE_AUTOMOTIVE"
+fi
+
+AM_CONDITIONAL(USE_FEATURE_AUTOMOTIVE, test "x${with_auto_feature}" = "xyes")
+
+# External AP
+AC_ARG_WITH([external_ap],
+ AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
+ [Using External Application Processor]),
+ [],
+ with_external_ap=no)
+
+if test "x$with_external_ap" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
+fi
+
+AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ loc-core.pc \
+ ])
+
+AC_OUTPUT
diff --git a/gps/core/data-items/DataItemConcreteTypesBase.h b/gps/core/data-items/DataItemConcreteTypesBase.h
new file mode 100644
index 0000000..11a3cce
--- /dev/null
+++ b/gps/core/data-items/DataItemConcreteTypesBase.h
@@ -0,0 +1,555 @@
+/* Copyright (c) 2015-2017, 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __DATAITEMCONCRETEBASETYPES__
+#define __DATAITEMCONCRETEBASETYPES__
+
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <DataItemId.h>
+#include <IDataItemCore.h>
+#include <gps_extended_c.h>
+#include <inttypes.h>
+
+#define MAC_ADDRESS_LENGTH 6
+// MAC address length in bytes
+// QMI_LOC_SRN_MAC_ADDR_LENGTH_V02
+#define SRN_MAC_ADDRESS_LENGTH 6
+#define WIFI_SUPPLICANT_DEFAULT_STATE 0
+
+static constexpr char sDelimit = ':';
+
+namespace loc_core
+{
+using namespace std;
+
+enum NetworkType {
+ TYPE_MOBILE = 0,
+ TYPE_WIFI,
+ TYPE_ETHERNET,
+ TYPE_BLUETOOTH,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_WIMAX,
+ TYPE_PROXY,
+ TYPE_UNKNOWN,
+};
+
+typedef struct NetworkInfoType
+{
+ // Unique network handle ID
+ uint64_t networkHandle;
+ // Type of network for corresponding network handle
+ NetworkType networkType;
+ NetworkInfoType() : networkHandle(NETWORK_HANDLE_UNKNOWN), networkType(TYPE_UNKNOWN) {}
+ NetworkInfoType(string strObj) {
+ size_t posDelimit = strObj.find(sDelimit);
+
+ if ( posDelimit != string::npos) {
+ int32_t type = TYPE_UNKNOWN;
+ string handleStr = strObj.substr(0, posDelimit);
+ string typeStr = strObj.substr(posDelimit + 1, strObj.length() - posDelimit - 1);
+ stringstream(handleStr) >> networkHandle;
+ stringstream(typeStr) >> type;
+ networkType = (NetworkType) type;
+ } else {
+ networkHandle = NETWORK_HANDLE_UNKNOWN;
+ networkType = TYPE_UNKNOWN;
+ }
+ }
+ bool operator== (const NetworkInfoType& other) {
+ return ((networkHandle == other.networkHandle) && (networkType == other.networkType));
+ }
+ string toString() {
+ string valueStr;
+ valueStr.clear ();
+ char nethandle [32];
+ memset (nethandle, 0, 32);
+ snprintf(nethandle, sizeof(nethandle), "%" PRIu64, networkHandle);
+ valueStr += string(nethandle);
+ valueStr += sDelimit;
+ char type [12];
+ memset (type, 0, 12);
+ snprintf (type, 12, "%u", networkType);
+ valueStr += string (type);
+ return valueStr;
+ }
+} NetworkInfoType;
+
+
+class AirplaneModeDataItemBase : public IDataItemCore {
+public:
+ AirplaneModeDataItemBase(bool mode):
+ mMode(mode),
+ mId(AIRPLANEMODE_DATA_ITEM_ID) {}
+ virtual ~AirplaneModeDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mMode;
+
+protected:
+ DataItemId mId;
+};
+
+class ENHDataItemBase : public IDataItemCore {
+public:
+ ENHDataItemBase(bool enabled) :
+ mEnabled(enabled),
+ mId(ENH_DATA_ITEM_ID) {}
+ virtual ~ENHDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mEnabled;
+protected:
+ DataItemId mId;
+};
+
+class GPSStateDataItemBase : public IDataItemCore {
+public:
+ GPSStateDataItemBase(bool enabled) :
+ mEnabled(enabled),
+ mId(GPSSTATE_DATA_ITEM_ID) {}
+ virtual ~GPSStateDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mEnabled;
+protected:
+ DataItemId mId;
+};
+
+class NLPStatusDataItemBase : public IDataItemCore {
+public:
+ NLPStatusDataItemBase(bool enabled) :
+ mEnabled(enabled),
+ mId(NLPSTATUS_DATA_ITEM_ID) {}
+ virtual ~NLPStatusDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mEnabled;
+protected:
+ DataItemId mId;
+};
+
+class WifiHardwareStateDataItemBase : public IDataItemCore {
+public:
+ WifiHardwareStateDataItemBase(bool enabled) :
+ mEnabled(enabled),
+ mId(WIFIHARDWARESTATE_DATA_ITEM_ID) {}
+ virtual ~WifiHardwareStateDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mEnabled;
+protected:
+ DataItemId mId;
+};
+
+class ScreenStateDataItemBase : public IDataItemCore {
+public:
+ ScreenStateDataItemBase(bool state) :
+ mState(state),
+ mId(SCREEN_STATE_DATA_ITEM_ID) {}
+ virtual ~ScreenStateDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mState;
+protected:
+ DataItemId mId;
+};
+
+class PowerConnectStateDataItemBase : public IDataItemCore {
+public:
+ PowerConnectStateDataItemBase(bool state) :
+ mState(state),
+ mId(POWER_CONNECTED_STATE_DATA_ITEM_ID) {}
+ virtual ~PowerConnectStateDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mState;
+protected:
+ DataItemId mId;
+};
+
+class TimeZoneChangeDataItemBase : public IDataItemCore {
+public:
+ TimeZoneChangeDataItemBase(int64_t currTimeMillis, int32_t rawOffset, int32_t dstOffset) :
+ mCurrTimeMillis (currTimeMillis),
+ mRawOffsetTZ (rawOffset),
+ mDstOffsetTZ (dstOffset),
+ mId(TIMEZONE_CHANGE_DATA_ITEM_ID) {}
+ virtual ~TimeZoneChangeDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ int64_t mCurrTimeMillis;
+ int32_t mRawOffsetTZ;
+ int32_t mDstOffsetTZ;
+protected:
+ DataItemId mId;
+};
+
+class TimeChangeDataItemBase : public IDataItemCore {
+public:
+ TimeChangeDataItemBase(int64_t currTimeMillis, int32_t rawOffset, int32_t dstOffset) :
+ mCurrTimeMillis (currTimeMillis),
+ mRawOffsetTZ (rawOffset),
+ mDstOffsetTZ (dstOffset),
+ mId(TIME_CHANGE_DATA_ITEM_ID) {}
+ virtual ~TimeChangeDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ int64_t mCurrTimeMillis;
+ int32_t mRawOffsetTZ;
+ int32_t mDstOffsetTZ;
+protected:
+ DataItemId mId;
+};
+
+class ShutdownStateDataItemBase : public IDataItemCore {
+public:
+ ShutdownStateDataItemBase(bool state) :
+ mState (state),
+ mId(SHUTDOWN_STATE_DATA_ITEM_ID) {}
+ virtual ~ShutdownStateDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mState;
+protected:
+ DataItemId mId;
+};
+
+class AssistedGpsDataItemBase : public IDataItemCore {
+public:
+ AssistedGpsDataItemBase(bool enabled) :
+ mEnabled(enabled),
+ mId(ASSISTED_GPS_DATA_ITEM_ID) {}
+ virtual ~AssistedGpsDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ bool mEnabled;
+protected:
+ DataItemId mId;
+};
+
+class NetworkInfoDataItemBase : public IDataItemCore {
+public:
+ NetworkInfoDataItemBase(
+ NetworkType initialType, int32_t type, string typeName, string subTypeName,
+ bool available, bool connected, bool roaming, uint64_t networkHandle, string apn):
+ mAllTypes(typeToAllTypes(initialType)),
+ mType(type),
+ mTypeName(typeName),
+ mSubTypeName(subTypeName),
+ mAvailable(available),
+ mConnected(connected),
+ mRoaming(roaming),
+ mNetworkHandle(networkHandle),
+ mId(NETWORKINFO_DATA_ITEM_ID), mApn(apn) {
+ mAllNetworkHandles[0].networkHandle = networkHandle;
+ mAllNetworkHandles[0].networkType = initialType;
+ }
+ virtual ~NetworkInfoDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+ inline virtual NetworkType getType(void) const {
+ return (NetworkType)mType;
+ }
+ inline uint64_t getAllTypes() { return mAllTypes; }
+ inline NetworkInfoType* getNetworkHandle() {
+ return &mAllNetworkHandles[0];
+ }
+ // Data members
+ uint64_t mAllTypes;
+ int32_t mType;
+ string mTypeName;
+ string mSubTypeName;
+ bool mAvailable;
+ bool mConnected;
+ bool mRoaming;
+ NetworkInfoType mAllNetworkHandles[MAX_NETWORK_HANDLES];
+ uint64_t mNetworkHandle;
+ string mApn;
+protected:
+ DataItemId mId;
+ inline uint64_t typeToAllTypes(NetworkType type) {
+ return (type >= TYPE_UNKNOWN || type < TYPE_MOBILE) ? 0 : (1<<type);
+ }
+};
+
+class ServiceStatusDataItemBase : public IDataItemCore {
+public:
+ ServiceStatusDataItemBase(int32_t serviceState) :
+ mServiceState (serviceState),
+ mId(SERVICESTATUS_DATA_ITEM_ID) {}
+ virtual ~ServiceStatusDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ int32_t mServiceState;
+protected:
+ DataItemId mId;
+};
+
+class ModelDataItemBase : public IDataItemCore {
+public:
+ ModelDataItemBase(const string & name) :
+ mModel (name),
+ mId(MODEL_DATA_ITEM_ID) {}
+ virtual ~ModelDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ string mModel;
+protected:
+ DataItemId mId;
+};
+
+class ManufacturerDataItemBase : public IDataItemCore {
+public:
+ ManufacturerDataItemBase(const string & name) :
+ mManufacturer (name),
+ mId(MANUFACTURER_DATA_ITEM_ID) {}
+ virtual ~ManufacturerDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ string mManufacturer;
+protected:
+ DataItemId mId;
+};
+
+class RilServiceInfoDataItemBase : public IDataItemCore {
+public:
+ inline RilServiceInfoDataItemBase() :
+ mData(nullptr), mId(RILSERVICEINFO_DATA_ITEM_ID) {}
+ inline virtual ~RilServiceInfoDataItemBase() { if (nullptr != mData) free(mData); }
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+ inline RilServiceInfoDataItemBase(const RilServiceInfoDataItemBase& peer) :
+ RilServiceInfoDataItemBase() {
+ peer.setPeerData(*this);
+ }
+ inline virtual bool operator==(const RilServiceInfoDataItemBase& other) const {
+ return other.mData == mData;
+ }
+ inline virtual void setPeerData(RilServiceInfoDataItemBase& /*peer*/) const {}
+ void* mData;
+protected:
+ DataItemId mId;
+};
+
+class RilCellInfoDataItemBase : public IDataItemCore {
+public:
+ inline RilCellInfoDataItemBase() :
+ mData(nullptr), mId(RILCELLINFO_DATA_ITEM_ID) {}
+ inline virtual ~RilCellInfoDataItemBase() { if (nullptr != mData) free(mData); }
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+ inline RilCellInfoDataItemBase(const RilCellInfoDataItemBase& peer) :
+ RilCellInfoDataItemBase() {
+ peer.setPeerData(*this);
+ }
+ inline virtual bool operator==(const RilCellInfoDataItemBase& other) const {
+ return other.mData == mData;
+ }
+ inline virtual void setPeerData(RilCellInfoDataItemBase& /*peer*/) const {}
+ void* mData;
+protected:
+ DataItemId mId;
+};
+
+class WifiSupplicantStatusDataItemBase : public IDataItemCore {
+public:
+ WifiSupplicantStatusDataItemBase() :
+ mState((WifiSupplicantState)WIFI_SUPPLICANT_DEFAULT_STATE),
+ mApMacAddressValid(false),
+ mWifiApSsidValid(false),
+ mId(WIFI_SUPPLICANT_STATUS_DATA_ITEM_ID) {
+ memset (&mApMacAddress, 0, sizeof (mApMacAddress));
+ mWifiApSsid.clear();
+ }
+ virtual ~WifiSupplicantStatusDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+ // Data members
+ typedef enum WifiSupplicantState {
+ DISCONNECTED,
+ INTERFACE_DISABLED,
+ INACTIVE,
+ SCANNING,
+ AUTHENTICATING,
+ ASSOCIATING,
+ ASSOCIATED,
+ FOUR_WAY_HANDSHAKE,
+ GROUP_HANDSHAKE,
+ COMPLETED,
+ DORMANT,
+ UNINITIALIZED,
+ INVALID
+ } WifiSupplicantState;
+ /* Represents whether access point attach state*/
+ WifiSupplicantState mState;
+ /* Represents info on whether ap mac address is valid */
+ bool mApMacAddressValid;
+ /* Represents mac address of the wifi access point*/
+ uint8_t mApMacAddress[MAC_ADDRESS_LENGTH];
+ /* Represents info on whether ap SSID is valid */
+ bool mWifiApSsidValid;
+ /* Represents Wifi SSID string*/
+ string mWifiApSsid;
+protected:
+ DataItemId mId;
+};
+
+class TacDataItemBase : public IDataItemCore {
+public:
+ TacDataItemBase(const string & name) :
+ mValue (name),
+ mId(TAC_DATA_ITEM_ID) {}
+ virtual ~TacDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ string mValue;
+protected:
+ DataItemId mId;
+};
+
+class MccmncDataItemBase : public IDataItemCore {
+public:
+ MccmncDataItemBase(const string & name) :
+ mValue(name),
+ mId(MCCMNC_DATA_ITEM_ID) {}
+ virtual ~MccmncDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+// Data members
+ string mValue;
+protected:
+ DataItemId mId;
+};
+
+class SrnDeviceScanDetailsDataItemBase : public IDataItemCore {
+public:
+ SrnDeviceScanDetailsDataItemBase(DataItemId Id) :
+ mValidSrnData(false),
+ mApSrnRssi(-1),
+ mApSrnTimestamp(0),
+ mRequestTimestamp(0),
+ mReceiveTimestamp(0),
+ mErrorCause(-1),
+ mId(Id) {}
+ virtual ~SrnDeviceScanDetailsDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+ // Data members common to all SRN tech types
+ /* Represents info on whether SRN data is valid (no error)*/
+ bool mValidSrnData;
+ /* SRN device RSSI reported */
+ int32_t mApSrnRssi;
+ /* MAC adress of SRN device */
+ uint8_t mApSrnMacAddress[SRN_MAC_ADDRESS_LENGTH];
+ /* UTC timestamp at which the scan was requested.for this SRN device*/
+ int64_t mApSrnTimestamp;
+ /* UTC timestamp at which the scan was started. */
+ int64_t mRequestTimestamp;
+ /* UTC timestamp at which the scan was received.*/
+ int64_t mReceiveTimestamp;
+ /* Reason for the error/failure if SRN details are not valid */
+ int32_t mErrorCause;
+protected:
+ DataItemId mId;
+};
+
+class BtDeviceScanDetailsDataItemBase : public SrnDeviceScanDetailsDataItemBase {
+
+public:
+ BtDeviceScanDetailsDataItemBase() :
+ SrnDeviceScanDetailsDataItemBase(BT_SCAN_DATA_ITEM_ID) {}
+ virtual ~BtDeviceScanDetailsDataItemBase() {}
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+};
+
+class BtLeDeviceScanDetailsDataItemBase : public SrnDeviceScanDetailsDataItemBase {
+
+public:
+ BtLeDeviceScanDetailsDataItemBase() :
+ SrnDeviceScanDetailsDataItemBase(BTLE_SCAN_DATA_ITEM_ID) {}
+ virtual ~BtLeDeviceScanDetailsDataItemBase() {}
+ virtual void stringify(string& /*valueStr*/) {}
+ virtual int32_t copy(IDataItemCore* /*src*/, bool* /*dataItemCopied = NULL*/) {return 1;}
+};
+
+class BatteryLevelDataItemBase : public IDataItemCore {
+public:
+ inline BatteryLevelDataItemBase(uint8_t batteryPct) :
+ mBatteryPct(batteryPct), mId(BATTERY_LEVEL_DATA_ITEM_ID) {}
+ inline ~BatteryLevelDataItemBase() {}
+ inline virtual DataItemId getId() { return mId; }
+// Data members
+ uint8_t mBatteryPct;
+protected:
+ DataItemId mId;
+};
+
+} // namespace loc_core
+
+#endif //__DATAITEMCONCRETEBASETYPES__
diff --git a/gps/core/data-items/DataItemId.h b/gps/core/data-items/DataItemId.h
new file mode 100644
index 0000000..1661be6
--- /dev/null
+++ b/gps/core/data-items/DataItemId.h
@@ -0,0 +1,79 @@
+/* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __DATAITEMID_H__
+#define __DATAITEMID_H__
+
+/**
+ * Enumeration of Data Item types
+ * When add/remove/update changes are made to Data Items, this file needs to be updated
+ * accordingly
+ */
+typedef enum e_DataItemId {
+ INVALID_DATA_ITEM_ID = -1,
+ // 0 - 4
+ AIRPLANEMODE_DATA_ITEM_ID,
+ ENH_DATA_ITEM_ID,
+ GPSSTATE_DATA_ITEM_ID,
+ NLPSTATUS_DATA_ITEM_ID,
+ WIFIHARDWARESTATE_DATA_ITEM_ID,
+ // 5 - 9
+ NETWORKINFO_DATA_ITEM_ID,
+ RILVERSION_DATA_ITEM_ID,
+ RILSERVICEINFO_DATA_ITEM_ID,
+ RILCELLINFO_DATA_ITEM_ID,
+ SERVICESTATUS_DATA_ITEM_ID,
+ // 10 - 14
+ MODEL_DATA_ITEM_ID,
+ MANUFACTURER_DATA_ITEM_ID,
+ VOICECALL_DATA_ITEM,
+ ASSISTED_GPS_DATA_ITEM_ID,
+ SCREEN_STATE_DATA_ITEM_ID,
+ // 15 - 19
+ POWER_CONNECTED_STATE_DATA_ITEM_ID,
+ TIMEZONE_CHANGE_DATA_ITEM_ID,
+ TIME_CHANGE_DATA_ITEM_ID,
+ WIFI_SUPPLICANT_STATUS_DATA_ITEM_ID,
+ SHUTDOWN_STATE_DATA_ITEM_ID,
+ // 20 - 24
+ TAC_DATA_ITEM_ID,
+ MCCMNC_DATA_ITEM_ID,
+ BTLE_SCAN_DATA_ITEM_ID,
+ BT_SCAN_DATA_ITEM_ID,
+ OEM_GTP_UPLOAD_TRIGGER_READY_ITEM_ID,
+
+ MAX_DATA_ITEM_ID,
+
+ // 26 -
+ BATTERY_LEVEL_DATA_ITEM_ID,
+
+ MAX_DATA_ITEM_ID_1_1,
+} DataItemId;
+
+#endif // #ifndef __DATAITEMID_H__
diff --git a/gps/core/data-items/DataItemsFactoryProxy.cpp b/gps/core/data-items/DataItemsFactoryProxy.cpp
new file mode 100644
index 0000000..10f73f4
--- /dev/null
+++ b/gps/core/data-items/DataItemsFactoryProxy.cpp
@@ -0,0 +1,82 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "DataItemsFactoryProxy"
+
+#include <dlfcn.h>
+#include <DataItemId.h>
+#include <IDataItemCore.h>
+#include <DataItemsFactoryProxy.h>
+#include <loc_pla.h>
+#include <log_util.h>
+#include "loc_misc_utils.h"
+
+namespace loc_core
+{
+void* DataItemsFactoryProxy::dataItemLibHandle = NULL;
+get_concrete_data_item_fn* DataItemsFactoryProxy::getConcreteDIFunc = NULL;
+
+IDataItemCore* DataItemsFactoryProxy::createNewDataItem(DataItemId id)
+{
+ IDataItemCore *mydi = nullptr;
+
+ if (NULL != getConcreteDIFunc) {
+ mydi = (*getConcreteDIFunc)(id);
+ }
+ else {
+ getConcreteDIFunc = (get_concrete_data_item_fn * )
+ dlGetSymFromLib(dataItemLibHandle, DATA_ITEMS_LIB_NAME, DATA_ITEMS_GET_CONCRETE_DI);
+
+ if (NULL != getConcreteDIFunc) {
+ LOC_LOGd("Loaded function %s : %p", DATA_ITEMS_GET_CONCRETE_DI, getConcreteDIFunc);
+ mydi = (*getConcreteDIFunc)(id);
+ }
+ else {
+ // dlysm failed.
+ const char * err = dlerror();
+ if (NULL == err)
+ {
+ err = "Unknown";
+ }
+ LOC_LOGe("failed to find symbol %s; error=%s", DATA_ITEMS_GET_CONCRETE_DI, err);
+ }
+ }
+ return mydi;
+}
+
+void DataItemsFactoryProxy::closeDataItemLibraryHandle()
+{
+ if (NULL != dataItemLibHandle) {
+ dlclose(dataItemLibHandle);
+ dataItemLibHandle = NULL;
+ }
+}
+
+} // namespace loc_core
+
+
diff --git a/gps/core/data-items/DataItemsFactoryProxy.h b/gps/core/data-items/DataItemsFactoryProxy.h
new file mode 100644
index 0000000..cfd447d
--- /dev/null
+++ b/gps/core/data-items/DataItemsFactoryProxy.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __DATAITEMFACTORYBASE__
+#define __DATAITEMFACTORYBASE__
+
+#include <DataItemId.h>
+#include <IDataItemCore.h>
+
+namespace loc_core
+{
+
+#define DATA_ITEMS_LIB_NAME "libdataitems.so"
+#define DATA_ITEMS_GET_CONCRETE_DI "getConcreteDataItem"
+
+typedef IDataItemCore * (get_concrete_data_item_fn)(DataItemId);
+
+class DataItemsFactoryProxy {
+public:
+ static IDataItemCore* createNewDataItem(DataItemId id);
+ static void closeDataItemLibraryHandle();
+ static void *dataItemLibHandle;
+ static get_concrete_data_item_fn *getConcreteDIFunc;
+};
+
+} // namespace loc_core
+
+#endif //__DATAITEMFACTORYBASE__
+
diff --git a/gps/core/data-items/IDataItemCore.h b/gps/core/data-items/IDataItemCore.h
new file mode 100644
index 0000000..6084c92
--- /dev/null
+++ b/gps/core/data-items/IDataItemCore.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __IDATAITEMCORE_H__
+#define __IDATAITEMCORE_H__
+
+#include <string>
+#include <DataItemId.h>
+
+namespace loc_core {
+
+using namespace std;
+
+/**
+ * @brief IDataItemCore interface.
+ * @details IDataItemCore interface.
+ *
+ */
+class IDataItemCore {
+public:
+ /**
+ * @brief Gets Data item id.
+ * @details Gets Data item id.
+ * @return Data item id.
+ */
+ virtual DataItemId getId () = 0;
+
+ /**
+ * @brief Stringify.
+ * @details Stringify.
+ *
+ * @param valueStr Reference to string.
+ */
+ virtual void stringify (string & valueStr) = 0;
+
+ /**
+ * @brief copy.
+ * @details copy.
+ *
+ * @param src Where to copy from.
+ * @param dataItemCopied Boolean flag indicated whether or not copied.
+ *
+ * @return Zero for success or non zero for failure.
+ */
+ virtual int32_t copy (IDataItemCore * src, bool *dataItemCopied = nullptr) = 0;
+
+ /**
+ * @brief Destructor.
+ * @details Destructor.
+ */
+ virtual ~IDataItemCore () {}
+};
+
+} // namespace loc_core
+
+#endif // __IDATAITEMCORE_H__
diff --git a/gps/core/loc-core.pc.in b/gps/core/loc-core.pc.in
new file mode 100644
index 0000000..76b514c
--- /dev/null
+++ b/gps/core/loc-core.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: loc-core
+Description: QTI GPS Loc Core
+Version: @VERSION@
+Libs: -L${libdir} -lloc_core
+Cflags: -I${includedir}/loc-core
diff --git a/gps/core/loc_core_log.cpp b/gps/core/loc_core_log.cpp
new file mode 100644
index 0000000..904f94b
--- /dev/null
+++ b/gps/core/loc_core_log.cpp
@@ -0,0 +1,215 @@
+/* Copyright (c) 2011-2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_core_log"
+
+#include <log_util.h>
+#include <loc_log.h>
+#include <loc_core_log.h>
+#include <loc_pla.h>
+
+void LocPosMode::logv() const
+{
+ LOC_LOGV ("Position mode: %s\n Position recurrence: %s\n "
+ "min interval: %d\n preferred accuracy: %d\n "
+ "preferred time: %d\n credentials: %s provider: %s \n "
+ "power mode: %d\n tbm %d",
+ loc_get_position_mode_name(mode),
+ loc_get_position_recurrence_name(recurrence),
+ min_interval,
+ preferred_accuracy,
+ preferred_time,
+ credentials,
+ provider,
+ powerMode,
+ timeBetweenMeasurements);
+}
+
+/* GPS status names */
+DECLARE_TBL(gps_status_name) =
+{
+ NAME_VAL( LOC_GPS_STATUS_NONE ),
+ NAME_VAL( LOC_GPS_STATUS_SESSION_BEGIN ),
+ NAME_VAL( LOC_GPS_STATUS_SESSION_END ),
+ NAME_VAL( LOC_GPS_STATUS_ENGINE_ON ),
+ NAME_VAL( LOC_GPS_STATUS_ENGINE_OFF ),
+};
+
+/* Find Android GPS status name */
+const char* loc_get_gps_status_name(LocGpsStatusValue gps_status)
+{
+ return loc_get_name_from_val(gps_status_name_tbl, (int64_t) gps_status);
+}
+
+
+
+DECLARE_TBL(loc_eng_position_modes) =
+{
+ NAME_VAL( LOC_POSITION_MODE_STANDALONE ),
+ NAME_VAL( LOC_POSITION_MODE_MS_BASED ),
+ NAME_VAL( LOC_POSITION_MODE_MS_ASSISTED ),
+ NAME_VAL( LOC_POSITION_MODE_RESERVED_1 ),
+ NAME_VAL( LOC_POSITION_MODE_RESERVED_2 ),
+ NAME_VAL( LOC_POSITION_MODE_RESERVED_3 ),
+ NAME_VAL( LOC_POSITION_MODE_RESERVED_4 ),
+ NAME_VAL( LOC_POSITION_MODE_RESERVED_5 )
+};
+
+const char* loc_get_position_mode_name(LocGpsPositionMode mode)
+{
+ return loc_get_name_from_val(loc_eng_position_modes_tbl, (int64_t) mode);
+}
+
+
+
+DECLARE_TBL(loc_eng_position_recurrences) =
+{
+ NAME_VAL( LOC_GPS_POSITION_RECURRENCE_PERIODIC ),
+ NAME_VAL( LOC_GPS_POSITION_RECURRENCE_SINGLE )
+};
+
+const char* loc_get_position_recurrence_name(LocGpsPositionRecurrence recur)
+{
+ return loc_get_name_from_val(loc_eng_position_recurrences_tbl, (int64_t) recur);
+}
+
+const char* loc_get_aiding_data_mask_names(LocGpsAidingData /*data*/)
+{
+ return NULL;
+}
+
+
+DECLARE_TBL(loc_eng_agps_types) =
+{
+ NAME_VAL( LOC_AGPS_TYPE_INVALID ),
+ NAME_VAL( LOC_AGPS_TYPE_ANY ),
+ NAME_VAL( LOC_AGPS_TYPE_SUPL ),
+ NAME_VAL( LOC_AGPS_TYPE_C2K ),
+ NAME_VAL( LOC_AGPS_TYPE_WWAN_ANY )
+};
+
+const char* loc_get_agps_type_name(LocAGpsType type)
+{
+ return loc_get_name_from_val(loc_eng_agps_types_tbl, (int64_t) type);
+}
+
+
+DECLARE_TBL(loc_eng_ni_types) =
+{
+ NAME_VAL( LOC_GPS_NI_TYPE_VOICE ),
+ NAME_VAL( LOC_GPS_NI_TYPE_UMTS_SUPL ),
+ NAME_VAL( LOC_GPS_NI_TYPE_UMTS_CTRL_PLANE ),
+ NAME_VAL( LOC_GPS_NI_TYPE_EMERGENCY_SUPL )
+};
+
+const char* loc_get_ni_type_name(LocGpsNiType type)
+{
+ return loc_get_name_from_val(loc_eng_ni_types_tbl, (int64_t) type);
+}
+
+
+DECLARE_TBL(loc_eng_ni_responses) =
+{
+ NAME_VAL( LOC_GPS_NI_RESPONSE_ACCEPT ),
+ NAME_VAL( LOC_GPS_NI_RESPONSE_DENY ),
+ NAME_VAL( LOC_GPS_NI_RESPONSE_DENY )
+};
+
+const char* loc_get_ni_response_name(LocGpsUserResponseType response)
+{
+ return loc_get_name_from_val(loc_eng_ni_responses_tbl, (int64_t) response);
+}
+
+
+DECLARE_TBL(loc_eng_ni_encodings) =
+{
+ NAME_VAL( LOC_GPS_ENC_NONE ),
+ NAME_VAL( LOC_GPS_ENC_SUPL_GSM_DEFAULT ),
+ NAME_VAL( LOC_GPS_ENC_SUPL_UTF8 ),
+ NAME_VAL( LOC_GPS_ENC_SUPL_UCS2 ),
+ NAME_VAL( LOC_GPS_ENC_UNKNOWN )
+};
+
+const char* loc_get_ni_encoding_name(LocGpsNiEncodingType encoding)
+{
+ return loc_get_name_from_val(loc_eng_ni_encodings_tbl, (int64_t) encoding);
+}
+
+DECLARE_TBL(loc_eng_agps_bears) =
+{
+ NAME_VAL( AGPS_APN_BEARER_INVALID ),
+ NAME_VAL( AGPS_APN_BEARER_IPV4 ),
+ NAME_VAL( AGPS_APN_BEARER_IPV6 ),
+ NAME_VAL( AGPS_APN_BEARER_IPV4V6 )
+};
+
+const char* loc_get_agps_bear_name(AGpsBearerType bearer)
+{
+ return loc_get_name_from_val(loc_eng_agps_bears_tbl, (int64_t) bearer);
+}
+
+DECLARE_TBL(loc_eng_server_types) =
+{
+ NAME_VAL( LOC_AGPS_CDMA_PDE_SERVER ),
+ NAME_VAL( LOC_AGPS_CUSTOM_PDE_SERVER ),
+ NAME_VAL( LOC_AGPS_MPC_SERVER ),
+ NAME_VAL( LOC_AGPS_SUPL_SERVER )
+};
+
+const char* loc_get_server_type_name(LocServerType type)
+{
+ return loc_get_name_from_val(loc_eng_server_types_tbl, (int64_t) type);
+}
+
+DECLARE_TBL(loc_eng_position_sess_status_types) =
+{
+ NAME_VAL( LOC_SESS_SUCCESS ),
+ NAME_VAL( LOC_SESS_INTERMEDIATE ),
+ NAME_VAL( LOC_SESS_FAILURE )
+};
+
+const char* loc_get_position_sess_status_name(enum loc_sess_status status)
+{
+ return loc_get_name_from_val(loc_eng_position_sess_status_types_tbl, (int64_t) status);
+}
+
+DECLARE_TBL(loc_eng_agps_status_names) =
+{
+ NAME_VAL( LOC_GPS_REQUEST_AGPS_DATA_CONN ),
+ NAME_VAL( LOC_GPS_RELEASE_AGPS_DATA_CONN ),
+ NAME_VAL( LOC_GPS_AGPS_DATA_CONNECTED ),
+ NAME_VAL( LOC_GPS_AGPS_DATA_CONN_DONE ),
+ NAME_VAL( LOC_GPS_AGPS_DATA_CONN_FAILED )
+};
+
+const char* loc_get_agps_status_name(LocAGpsStatusValue status)
+{
+ return loc_get_name_from_val(loc_eng_agps_status_names_tbl, (int64_t) status);
+}
diff --git a/gps/core/loc_core_log.h b/gps/core/loc_core_log.h
new file mode 100644
index 0000000..2beb687
--- /dev/null
+++ b/gps/core/loc_core_log.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2011-2013, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_CORE_LOG_H
+#define LOC_CORE_LOG_H
+
+#include <ctype.h>
+#include <gps_extended.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+const char* loc_get_gps_status_name(LocGpsStatusValue gps_status);
+const char* loc_get_position_mode_name(LocGpsPositionMode mode);
+const char* loc_get_position_recurrence_name(LocGpsPositionRecurrence recur);
+const char* loc_get_aiding_data_mask_names(LocGpsAidingData data);
+const char* loc_get_agps_type_name(LocAGpsType type);
+const char* loc_get_ni_type_name(LocGpsNiType type);
+const char* loc_get_ni_response_name(LocGpsUserResponseType response);
+const char* loc_get_ni_encoding_name(LocGpsNiEncodingType encoding);
+const char* loc_get_agps_bear_name(AGpsBearerType bear);
+const char* loc_get_server_type_name(LocServerType type);
+const char* loc_get_position_sess_status_name(enum loc_sess_status status);
+const char* loc_get_agps_status_name(LocAGpsStatusValue status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOC_CORE_LOG_H */
diff --git a/gps/core/observer/IDataItemObserver.h b/gps/core/observer/IDataItemObserver.h
new file mode 100644
index 0000000..7954d85
--- /dev/null
+++ b/gps/core/observer/IDataItemObserver.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __IDATAITEMOBSERVER_H__
+#define __IDATAITEMOBSERVER_H__
+
+#include <list>
+#include <string>
+
+using namespace std;
+
+namespace loc_core
+{
+class IDataItemCore;
+
+/**
+ * @brief IDataItemObserver interface
+ * @details IDataItemObserver interface;
+ * In OS dependent code this type serves as a handle to an OS independent instance of this interface.
+ */
+class IDataItemObserver {
+
+public:
+
+ /**
+ * @brief Gets name of Data Item Observer
+ * @details Gets name of Data Item Observer
+ *
+ * @param name reference to name of Data Item Observer
+ */
+ virtual void getName (string & name) = 0;
+
+ /**
+ * @brief Notify updated values of Data Items
+ * @details Notifys updated values of Data items
+ *
+ * @param dlist List of updated data items
+ */
+ virtual void notify (const std :: list <IDataItemCore *> & dlist) = 0;
+
+ /**
+ * @brief Destructor
+ * @details Destructor
+ */
+ virtual ~IDataItemObserver () {}
+};
+
+} // namespace loc_core
+
+#endif // #ifndef __IDATAITEMOBSERVER_H__
diff --git a/gps/core/observer/IDataItemSubscription.h b/gps/core/observer/IDataItemSubscription.h
new file mode 100644
index 0000000..7e8b8c8
--- /dev/null
+++ b/gps/core/observer/IDataItemSubscription.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __IDATAITEMSUBSCRIPTION_H__
+#define __IDATAITEMSUBSCRIPTION_H__
+
+#include <list>
+#include <DataItemId.h>
+
+namespace loc_core
+{
+class IDataItemObserver;
+
+/**
+ * @brief IDataItemSubscription interface
+ * @details IDataItemSubscription interface;
+ * Defines an interface for operations such as subscribe,
+ * unsubscribe data items by their IDs.
+ * Must be implemented by OS dependent code.
+ */
+class IDataItemSubscription {
+
+public:
+ /**
+ * @brief Subscribe for data items by their IDs
+ * @details Subscribe for data items by their IDs;
+ * An IDataItemObserver implementer invokes this method to subscribe
+ * for a list of DataItems by passing in their Ids.
+ * A symbolic invocation of this method in the following order
+ * subscribe ( {1,2,3}, &obj), subscribe ( {2,3,4,5}, &obj)
+ * where the numbers enclosed in braces indicate a list of data item Ids
+ * will cause this class implementer to update its subscription list for
+ * &obj to only contain the following Data Item Ids 1,2,3,4,5.
+ *
+ * @param l List of DataItemId
+ * @param o Pointer to an instance of IDataItemObserver
+ */
+ virtual void subscribe (const std :: list <DataItemId> & l, IDataItemObserver * o = NULL) = 0;
+
+ /**
+ * @brief Update subscription for Data items
+ * @details Update subscription for Data items;
+ * An IDataItemObserver implementer invokes this method to update their
+ * subscription for a list of DataItems by passing in their Ids
+ * A symbolic invocation of this method in the following order
+ * updateSubscription ( {1,2,3}, &obj),updateSubscription ( {2,3,4,5}, &obj)
+ * where the numbers enclosed in braces indicate a list of data item Ids
+ * will cause this class implementer to update its subscription list for
+ * &obj to only contain the following Data Item Ids 2,3,4,5.
+ * Note that this method may or may not be called.
+ *
+ * @param l List of DataItemId
+ * @param o Pointer to an instance of IDataItemObserver
+ */
+ virtual void updateSubscription (const std :: list <DataItemId> & l, IDataItemObserver * o = NULL) = 0;
+
+ /**
+ * @brief Request Data
+ * @details Request Data
+ *
+ * @param l List of DataItemId
+ * @param o Pointer to an instance of IDataItemObserver
+ */
+ virtual void requestData (const std :: list <DataItemId> & l, IDataItemObserver * o = NULL) = 0;
+
+ /**
+ * @brief Unsubscribe Data items
+ * @details Unsubscrbe Data items;
+ * An IDataItemObserver implementer invokes this method to unsubscribe their
+ * subscription for a list of DataItems by passing in their Ids
+ * Suppose this class implementor has a currently active subscription list
+ * containing 1,2,3,4,5,6,7 for &obj then a symbolic invocation of this
+ * method in the following order
+ * unsubscribe ( {1,2,3}, &obj), unsubscribe ( {1,2,3,4}, &obj),
+ * unsubscribe ( {7}, &obj)
+ * where the numbers enclosed in braces indicate a list of data item Ids
+ * will cause this class implementer to update its subscription list for
+ * &obj to only contain the following data item id 5,6.
+ *
+ * @param l List of DataItemId
+ * @param o Pointer to an instance of IDataItemObserver
+ */
+ virtual void unsubscribe (const std :: list <DataItemId> & l, IDataItemObserver * o = NULL) = 0;
+
+ /**
+ * @brief Unsubscribe all data items
+ * @details Unsubscribe all data items
+ *
+ * @param o Pointer to an instance of IDataItemObserver
+ */
+ virtual void unsubscribeAll (IDataItemObserver * o = NULL) = 0;
+
+ /**
+ * @brief Destructor
+ * @details Destructor
+ */
+ virtual ~IDataItemSubscription () {}
+};
+
+} // namespace loc_core
+
+#endif // #ifndef __IDATAITEMSUBSCRIPTION_H__
+
diff --git a/gps/core/observer/IFrameworkActionReq.h b/gps/core/observer/IFrameworkActionReq.h
new file mode 100644
index 0000000..138508c
--- /dev/null
+++ b/gps/core/observer/IFrameworkActionReq.h
@@ -0,0 +1,104 @@
+/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __IFRAMEWORKACTIONREQ_H__
+#define __IFRAMEWORKACTIONREQ_H__
+
+#include <string>
+#include <DataItemId.h>
+
+using namespace std;
+
+namespace loc_core
+{
+
+/**
+ * @brief IFrameworkActionReq interface
+ * @details IFrameworkActionReq interface;
+ * Defines an interface for operations such as turnOn, turnOff a
+ * framework module described by the data item. Framework module
+ * could be bluetooth, wifi etc.
+ * Must be implemented by OS dependent code.
+ *
+ */
+class IFrameworkActionReq {
+
+public:
+ /**
+ * @brief Turn on the framework module described by the data item.
+ * @details Turn on the framework module described by the data item;
+ * An IFrameworkActionReq implementer invokes this method to
+ * turn on the framework module described by the data item.
+ * Framework module could be bluetooth, wifi etc.
+ *
+ * @param dit DataItemId
+ * @param timeout Timeout after which to turn off the framework module.
+ */
+ virtual void turnOn (DataItemId dit, int timeOut = 0) = 0;
+
+ /**
+ * @brief Turn off the framework module described by the data item.
+ * @details Turn off the framework module described by the data item;
+ * An IFrameworkActionReq implementer invokes this method to
+ * turn off the framework module described by the data item.
+ * Framework module could be bluetooth, wifi etc.
+ *
+ * @param dit DataItemId
+ */
+ virtual void turnOff (DataItemId dit) = 0;
+
+#ifdef USE_GLIB
+ /**
+ * @brief Setup WWAN backhaul
+ * @details Setup WWAN backhaul
+ *
+ * @param None
+ */
+ virtual bool connectBackhaul(const string& clientName) = 0;
+
+ /**
+ * @brief Disconnects the WWANbackhaul
+ * @details Disconnects the WWANbackhaul, only if it was setup by us
+ *
+ * @param None
+ */
+ virtual bool disconnectBackhaul(const string& clientName) = 0;
+#endif
+
+ /**
+ * @brief Destructor
+ * @details Destructor
+ */
+ virtual ~IFrameworkActionReq () {}
+};
+
+} // namespace loc_core
+
+#endif // #ifndef __IFRAMEWORKACTIONREQ_H__
+
diff --git a/gps/core/observer/IOsObserver.h b/gps/core/observer/IOsObserver.h
new file mode 100644
index 0000000..a25bb9f
--- /dev/null
+++ b/gps/core/observer/IOsObserver.h
@@ -0,0 +1,107 @@
+/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __IOSOBSERVER_H__
+#define __IOSOBSERVER_H__
+
+#include <list>
+#include <string>
+#include <IDataItemObserver.h>
+#include <IDataItemSubscription.h>
+#include <IFrameworkActionReq.h>
+
+using namespace std;
+
+namespace loc_core
+{
+
+/**
+ * @brief IOsObserver interface
+ * @details IOsObserver interface;
+ * In OS dependent code this type serves as a handle to
+ * an OS independent instance of this interface.
+ */
+class IOsObserver :
+ public IDataItemObserver,
+ public IDataItemSubscription,
+ public IFrameworkActionReq {
+
+public:
+
+ // To set the subscription object
+ virtual void setSubscriptionObj(IDataItemSubscription *subscriptionObj) = 0;
+
+ // To set the framework action request object
+ virtual void setFrameworkActionReqObj(IFrameworkActionReq *frameworkActionReqObj) = 0;
+
+ // IDataItemObserver Overrides
+ inline virtual void getName (string & /*name*/) {}
+ inline virtual void notify (const std::list <IDataItemCore *> & /*dlist*/) {}
+
+ // IDataItemSubscription Overrides
+ inline virtual void subscribe
+ (
+ const std :: list <DataItemId> & /*l*/,
+ IDataItemObserver * /*client*/
+ ){}
+ inline virtual void updateSubscription
+ (
+ const std :: list <DataItemId> & /*l*/,
+ IDataItemObserver * /*client*/
+ ){}
+ inline virtual void requestData
+ (
+ const std :: list <DataItemId> & /*l*/,
+ IDataItemObserver * /*client*/
+ ){}
+ inline virtual void unsubscribe
+ (
+ const std :: list <DataItemId> & /*l*/,
+ IDataItemObserver * /*client*/
+ ){}
+ inline virtual void unsubscribeAll (IDataItemObserver * /*client*/){}
+
+ // IFrameworkActionReq Overrides
+ inline virtual void turnOn (DataItemId /*dit*/, int /*timeOut*/){}
+ inline virtual void turnOff (DataItemId /*dit*/) {}
+#ifdef USE_GLIB
+ inline virtual bool connectBackhaul(const string& clientName) { return false; }
+ inline virtual bool disconnectBackhaul(const string& clientName) { return false; }
+#endif
+
+ /**
+ * @brief Destructor
+ * @details Destructor
+ */
+ virtual ~IOsObserver () {}
+};
+
+} // namespace loc_core
+
+#endif // #ifndef __IOSOBSERVER_H__
diff --git a/gps/etc/Android.bp b/gps/etc/Android.bp
new file mode 100644
index 0000000..95f2e80
--- /dev/null
+++ b/gps/etc/Android.bp
@@ -0,0 +1,55 @@
+prebuilt_etc {
+ name: "apdr.conf",
+ vendor: true,
+ src: "apdr.conf",
+}
+
+prebuilt_etc {
+ name: "flp.conf",
+ vendor: true,
+ src: "flp.conf",
+}
+
+prebuilt_etc {
+ name: "gnss_antenna_info.conf",
+ vendor: true,
+ src: "gnss_antenna_info.conf",
+}
+
+prebuilt_etc {
+ name: "gps.conf",
+ vendor: true,
+ src: "gps.conf",
+}
+
+prebuilt_etc {
+ name: "izat.conf",
+ vendor: true,
+ src: "izat.conf",
+}
+
+prebuilt_etc {
+ name: "lowi.conf",
+ vendor: true,
+ src: "lowi.conf",
+}
+
+prebuilt_etc {
+ name: "sap.conf",
+ vendor: true,
+ src: "sap.conf",
+}
+
+prebuilt_etc {
+ name: "gnss@2.0-base.policy",
+ vendor: true,
+ sub_dir: "seccomp_policy",
+ src: "seccomp_policy/gnss@2.0-base.policy",
+}
+
+prebuilt_etc {
+ name: "gnss@2.0-xtra-daemon.policy",
+ vendor: true,
+ sub_dir: "seccomp_policy",
+ src: "seccomp_policy/gnss@2.0-xtra-daemon.policy",
+}
diff --git a/gps/etc/apdr.conf b/gps/etc/apdr.conf
new file mode 100644
index 0000000..ea2ec52
--- /dev/null
+++ b/gps/etc/apdr.conf
@@ -0,0 +1,183 @@
+# AP DR SENSOR Configuration file
+#
+# SENSOR_SERVICE options are one of below
+# accel,gyro,vehicle_accel,vehicle_gyro,pedometer,vehicle_odometry,accel_temp,
+# gyro_temp,baro,mag_calib,mag_uncalib,amd,rmd.
+#
+# SENSOR_PROVIDER options is one of -- default,native,ssc,samlite.
+#
+# SENSOR_RATE = 1~100 (Hz)
+#
+# SENSOR_SAMPLES = 1~N
+#
+# SENSOR_STATISTIC_ENABLED
+# bit 0: Diag Print Enabled
+# bit 1: Adb Print Enabled
+# SENSOR_STATISTIC_PRINT_COUNT
+# Skip Number of Print
+#
+# QDR_DYNAMIC_LOADING = 1~3
+# Configure QDR library to be loaded
+# 1: QDR3
+# 2: QDR2-GYRO
+# 3: QDR2-DWT
+#
+#
+
+######################################
+# #
+# QDR3 Configuration #
+# #
+# For QDR3, #
+# comment default configuration above#
+# and #
+# uncomment below configuration #
+# settings. #
+# #
+######################################
+#
+SENSOR_SERVICE = accel
+SENSOR_PROVIDER = native
+SENSOR_RATE = 10
+SENSOR_SAMPLES = 10
+#
+SENSOR_SERVICE = vehicle_speed
+SENSOR_PROVIDER = native
+SENSOR_RATE = 100
+SENSOR_SAMPLES = 1
+#
+SENSOR_SERVICE = gyro
+SENSOR_PROVIDER = native
+SENSOR_RATE = 10
+SENSOR_SAMPLES = 10
+#
+SENSOR_SERVICE = vehicle_gear
+SENSOR_PROVIDER = native
+SENSOR_RATE = 100
+SENSOR_SAMPLES = 1
+#
+SENSOR_SERVICE = accel_temp
+SENSOR_PROVIDER = native
+SENSOR_RATE = 1
+SENSOR_SAMPLES = 1
+#
+#
+##Configure QDR library to be loaded 1: QDR3 2: QDR2-GYRO 3: QDR2-DWS
+QDR_DYNAMIC_LOADING = 1
+##Specify CAN sensor type: Valid Options: 14(ODO), 2(ODO_DWT), 3(ODO_DWS)
+QDR_CAN_TYPE = 14
+##Reporting offset before PPS boundary
+QDR_REPORTING_OFFSET = 20
+#
+
+##Vehicle Sensor Configuration (CAN data availability)
+##QDR_VEH_SENSOR_CONFIG:
+## 0: VEHICLE_SENSOR_PRESENT - Vehicle Sensor is available (DEFAULT)
+## 1: VEHICLE_SENSOR_OPTIONAL - Vehicle Sensor may or may not be present.
+#QDR_VEH_SENSOR_CONFIG = 0
+
+##Select Wheel set (E.g.: Front two wheels, Rear two wheels OR All four wheels)
+##To be used for differential wheel tick OR speed service.
+##This configuration is applicable when QDR_CAN_TYPE configured as
+##ODO_DWS(3) or ODO_DWT(2).
+##Value "0": Use Front two wheels
+##Value "1": Use Rear two wheels
+##Value "2": Use All four wheels
+#QG_DRIVE_WHEEL_FW_RW_AW = 2
+##Max Wheel tick value above which wheel tick rolls over
+##This configuration is applicable when QDR_CAN_TYPE configured as ODO_DWT(2)
+#QG_DWT_MAX_WHEEL_TICK_COUNT = 255.0
+##Configure Wheel constant for DWT based below equation
+##(2 * pi * WHEEL_RADIUS / Pulses Per revolution)
+##This configuration is applicable when QDR_CAN_TYPE configured as ODO_DWT(2)
+#QG_DWT_WHEEL_CONSTANT = 0.044
+#
+
+######################################
+# #
+# QDR2-DWT Configuration #
+# #
+# For QDR2-DWT, #
+# comment default configuration above#
+# and #
+# uncomment below configuration #
+# settings. #
+# #
+######################################
+#
+#SENSOR_SERVICE = vehicle_speed
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#SENSOR_STATISTIC_ENABLED = 3
+#SENSOR_STATISTIC_PRINT_COUNT = 50
+#
+#SENSOR_SERVICE = vehicle_dws
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#SENSOR_STATISTIC_ENABLED = 3
+#SENSOR_STATISTIC_PRINT_COUNT = 50
+#
+#SENSOR_SERVICE = vehicle_gear
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#SENSOR_STATISTIC_ENABLED = 3
+#SENSOR_STATISTIC_PRINT_COUNT = 50
+#
+#GNSS_POS_STATISTIC_ENABLED = 3
+#GNSS_POS_STATISTIC_PRNTCNT = 10
+#GNSS_MSR_STATISTIC_ENABLED = 3
+#GNSS_MSR_STATISTIC_PRNTCNT = 10
+#
+##Configure QDR library to be loaded 1: QDR3 2: QDR2-GYRO 3: QDR2-DWS
+#QDR_DYNAMIC_LOADING = 3
+##Enable/disable sensor data flashback feature
+#QDR_FLASHBACK_ENABLED = 0
+##Enable/disable sensor data batching feature
+#QDR_BATCHING_ENABLED = 0
+##Reporting offset before PPS boundary
+#QDR_REPORTING_OFFSET = 20
+##Sensor dispatch threshold declaration
+#QDR_SENSDISPATCH_MS = 30
+
+
+######################################
+# #
+# QDR2-GYRO Configuration #
+# #
+# For QDR2-GYRO, #
+# comment default configuration above#
+# and #
+# uncomment below configuration #
+# settings. #
+# #
+######################################
+#
+#SENSOR_SERVICE = vehicle_speed
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#
+#SENSOR_SERVICE = vehicle_gyro
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#
+#SENSOR_SERVICE = vehicle_gear
+#SENSOR_PROVIDER = native
+#SENSOR_RATE = 100
+#SENSOR_SAMPLES = 1
+#
+##Configure QDR library to be loaded 1: QDR3 2: QDR2-GYRO 3: QDR2-DWS
+#QDR_DYNAMIC_LOADING = 2
+##Enable/disable sensor data flashback feature
+#QDR_FLASHBACK_ENABLED = 0
+##Enable/disable sensor data batching feature
+#QDR_BATCHING_ENABLED = 0
+##Reporting offset before PPS boundary
+#QDR_REPORTING_OFFSET = 20
+##Sensor dispatch threshold declaration
+#QDR_SENSDISPATCH_MS = 30
+#
diff --git a/gps/etc/flp.conf b/gps/etc/flp.conf
new file mode 100644
index 0000000..65d54d3
--- /dev/null
+++ b/gps/etc/flp.conf
@@ -0,0 +1,60 @@
+###################################
+##### FLP settings #####
+###################################
+
+###################################
+# FLP BATCH SIZE
+###################################
+# The number of batched locations
+# requested to modem. The desired number
+# defined below may not be satisfied, as
+# the modem can only return the number
+# of batched locations that can be allocated,
+# which is limited by memory. The default
+# batch size defined as 20 as below.
+BATCH_SIZE=20
+
+###################################
+# FLP OUTDOOR TRIP BATCH SIZE
+###################################
+# The number of batched locations
+# requested to modem for outdoor
+# trip batching. The desired number
+# defined below may not be satisfied, as
+# the modem can only return the number
+# of batched locations that can be allocated,
+# which is limited by memory. The default
+# trip batch size defined as 600 as below.
+OUTDOOR_TRIP_BATCH_SIZE=600
+
+###################################
+# FLP BATCHING SESSION TIMEOUT
+###################################
+# Duration with which batch session timeout
+# happens in milliseconds. If not specified
+# or set to zero, batching session timeout
+# defaults to 20 seconds by the modem.
+# BATCH_SESSION_TIMEOUT=20000
+
+###################################
+# FLP BATCHING ACCURACY
+###################################
+# Set to one of the defined values below
+# to define the accuracy of batching.
+# If not specified, accuracy defaults
+# to LOW.
+# FLP BATCHING ACCURACY values:
+# Low accuracy = 0
+# Medium accuracy = 1
+# High accuracy = 2
+ACCURACY=1
+
+####################################
+# By default if network fixes are not sensor assisted
+# these fixes must be dropped. This parameter adds an exception
+# for targets where there is no PDR and we still want to
+# report out network fixes
+# 0: MUST NOT ALLOW NETWORK FIXES
+# 1: ALLOW NETWORK FIXES
+####################################
+ALLOW_NETWORK_FIXES = 0
diff --git a/gps/etc/gnss_antenna_info.conf b/gps/etc/gnss_antenna_info.conf
new file mode 100644
index 0000000..79a2aef
--- /dev/null
+++ b/gps/etc/gnss_antenna_info.conf
@@ -0,0 +1,134 @@
+###################################
+##### ANTENNA INFORMATION #####
+###################################
+
+###################################
+# ANTENNA INFO VECTOR SIZE
+###################################
+# The number of antenna info
+# structures in the vector. Each
+# entry in this vector is a structure
+# with the following elements:
+#
+# - CARRIER_FREQUENCY
+# - PC_OFFSET
+# - PC_VARIATION_CORRECTION
+# - PC_VARIATION_CORRECTION_UNC
+# - SIGNAL_GAIN_CORRECTION
+# - SIGNAL_GAIN_CORRECTION_UNC
+#
+# Notes:
+# CARRIER_FREQUENCY
+# The carrier frequency in MHz.
+#
+# PC = PHASE CENTER
+# PC_OFFSET is a structure with six
+# elements: x, y, z and their associated uncertainties
+# Phase center offset (PCO) is defined with
+# respect to the origin of the Android sensor coordinate system, e.g.,
+# center of primary screen for mobiles
+#
+# PC_VARIATION_CORRECTION
+# 2D vectors representing the phase center variation (PCV) corrections,
+# in millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+# (phi). The PCV correction is added to the phase measurement to obtain the
+# corrected value.
+# The azimuthal angle, theta, is defined with respect to the X axis of the
+# Android sensor coordinate system, increasing toward the Y axis. The zenith
+# angle, phi, is defined with respect to the Z axis of the Android Sensor
+# coordinate system, increasing toward the X-Y plane.
+# Each row vector (outer vectors) represents a fixed theta. The first row
+# corresponds to a theta angle of 0 degrees. The last row corresponds to a
+# theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+# spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+# The columns (inner vectors) represent fixed zenith angles, beginning at 0
+# degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+# spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+#
+# PC_VARIATION_CORRECTION_UNC
+# 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+# correction values.
+#
+# SIGNAL_GAIN_CORRECTION
+# 2D vectors representing the signal gain corrections at regularly spaced
+# azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+# measured at the antenna feed point without considering the radio and receiver
+# noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+# antenna with the same total power. The signal gain correction is added the
+# signal gain measurement to obtain the corrected value.
+# The azimuthal angle, theta, is defined with respect to the X axis of the
+# Android sensor coordinate system, increasing toward the Y axis. The zenith
+# angle, phi, is defined with respect to the Z axis of the Android Sensor
+# coordinate system, increasing toward the X-Y plane.
+# Each row vector (outer vectors) represents a fixed theta. The first row
+# corresponds to a theta angle of 0 degrees. The last row corresponds to a
+# theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+# spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+# The columns (inner vectors) represent fixed zenith angles, beginning at 0
+# degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+# spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+#
+# SIGNAL_GAIN_CORRECTION_UNC
+# 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+# gain correction values.
+#
+# The number of rows and columns could be the same for PC variation correction
+# and signal gain corrections, or could be different
+# If the former then NUMBER_OF_ROWS_ and NUMBER_OF_COLUMNS_ are specified once
+# only, if the latter then NUMBER_OF_ROWS_ and NUMBER_OF_COLUMNS_ represent
+# the number of rows/columns for PC variation correction and
+# NUMBER_OF_ROWS_SGC_ and NUMBER_OF_COLUMNS_SGC_ represent the number of
+# rows/columns for signal gain corrections
+
+ANTENNA_INFO_VECTOR_SIZE = 2
+
+CARRIER_FREQUENCY_0 = 1575.42
+
+PC_OFFSET_0 = 1.2 0.1 3.4 0.2 5.6 0.3
+
+NUMBER_OF_ROWS_0 = 3
+NUMBER_OF_COLUMNS_0 = 4
+
+PC_VARIATION_CORRECTION_0_ROW_0 = 11.22 33.44 55.66 77.88
+PC_VARIATION_CORRECTION_0_ROW_1 = 10.2 30.4 50.6 70.8
+PC_VARIATION_CORRECTION_0_ROW_2 = 12.2 34.4 56.6 78.8
+
+PC_VARIATION_CORRECTION_UNC_0_ROW_0 = 0.1 0.2 0.3 0.4
+PC_VARIATION_CORRECTION_UNC_0_ROW_1 = 1.1 1.2 1.3 1.4
+PC_VARIATION_CORRECTION_UNC_0_ROW_2 = 2.1 2.2 2.3 2.4
+
+SIGNAL_GAIN_CORRECTION_0_ROW_0 = 9.8 8.7 7.6 6.5
+SIGNAL_GAIN_CORRECTION_0_ROW_1 = 5.4 4.3 3.2 2.1
+SIGNAL_GAIN_CORRECTION_0_ROW_2 = 1.3 2.4 3.5 4.6
+
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_0 = 0.11 0.22 0.33 0.44
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_1 = 0.55 0.66 0.77 0.88
+SIGNAL_GAIN_CORRECTION_UNC_0_ROW_2 = 0.91 0.92 0.93 0.94
+
+
+CARRIER_FREQUENCY_1 = 1227.6
+
+PC_OFFSET_1 = 3.4 0.2 5.6 0.3 1.2 0.1
+
+NUMBER_OF_ROWS_1 = 4
+NUMBER_OF_COLUMNS_1 = 2
+NUMBER_OF_ROWS_SGC_1 = 3
+NUMBER_OF_COLUMNS_SGC_1 = 4
+
+PC_VARIATION_CORRECTION_1_ROW_0 = 55.66 77.88
+PC_VARIATION_CORRECTION_1_ROW_1 = 11.22 33.44
+PC_VARIATION_CORRECTION_1_ROW_2 = 56.6 78.8
+PC_VARIATION_CORRECTION_1_ROW_3 = 12.2 34.4
+
+PC_VARIATION_CORRECTION_UNC_1_ROW_0 = 0.3 0.4
+PC_VARIATION_CORRECTION_UNC_1_ROW_1 = 1.1 1.2
+PC_VARIATION_CORRECTION_UNC_1_ROW_2 = 2.1 2.2
+PC_VARIATION_CORRECTION_UNC_1_ROW_3 = 0.1 0.2
+
+SIGNAL_GAIN_CORRECTION_1_ROW_0 = 7.6 6.5 5.4 4.3
+SIGNAL_GAIN_CORRECTION_1_ROW_1 = 1.3 2.4 9.8 8.7
+SIGNAL_GAIN_CORRECTION_1_ROW_2 = 1.4 2.5 3.6 4.7
+
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_0 = 0.91 0.92 0.55 0.66
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_1 = 0.11 0.22 0.93 0.94
+SIGNAL_GAIN_CORRECTION_UNC_1_ROW_2 = 0.95 0.96 0.33 0.44
diff --git a/gps/etc/gps.conf b/gps/etc/gps.conf
new file mode 100644
index 0000000..1bab008
--- /dev/null
+++ b/gps/etc/gps.conf
@@ -0,0 +1,391 @@
+# Error Estimate
+# _SET = 1
+# _CLEAR = 0
+ERR_ESTIMATE=0
+
+#NTP server
+NTP_SERVER=time.xtracloud.net
+
+#XTRA CA path
+XTRA_CA_PATH=/usr/lib/ssl-1.1/certs
+
+# DEBUG LEVELS: 0 - none, 1 - Error, 2 - Warning, 3 - Info
+# 4 - Debug, 5 - Verbose
+# If DEBUG_LEVEL is commented, Android's logging levels will be used
+DEBUG_LEVEL = 2
+
+# Intermediate position report, 1=enable, 0=disable
+INTERMEDIATE_POS=0
+
+# supl version 1.0
+SUPL_VER=0x10000
+
+# Emergency SUPL, 1=enable, 0=disable
+#SUPL_ES=1
+
+#Choose PDN for Emergency SUPL
+#1 - Use emergency PDN
+#0 - Use regular SUPL PDN for Emergency SUPL
+#USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=0
+
+#SUPL_MODE is a bit mask set in config.xml per carrier by default.
+#If it is uncommented here, this value will overwrite the value from
+#config.xml.
+#MSA=0X2
+#MSB=0X1
+#SUPL_MODE=
+
+# GPS Capabilities bit mask
+# SCHEDULING = 0x01
+# MSB = 0x02
+# MSA = 0x04
+# ON_DEMAND_TIME = 0x10
+# default = ON_DEMAND_TIME | MSA | MSB | SCHEDULING
+CAPABILITIES=0x17
+
+# Accuracy threshold for intermediate positions
+# less accurate positions are ignored, 0 for passing all positions
+# ACCURACY_THRES=5000
+
+################################
+##### AGPS server settings #####
+################################
+
+# FOR SUPL SUPPORT, set the following
+# SUPL_HOST=supl.host.com or IP
+# SUPL_PORT=1234
+
+# FOR MO SUPL SUPPORT, set the following
+# MO_SUPL_HOST=supl.host.com or IP
+# MO_SUPL_PORT=1234
+
+# FOR C2K PDE SUPPORT, set the following
+# C2K_HOST=c2k.pde.com or IP
+# C2K_PORT=1234
+
+# Bitmask of slots that are available
+# for write/install to, where 1s indicate writable,
+# and the default value is 0 where no slots
+# are writable. For example, AGPS_CERT_WRITABLE_MASK
+# of b1000001010 makes 3 slots available
+# and the remaining 7 slots unwritable.
+#AGPS_CERT_WRITABLE_MASK=0
+
+####################################
+# LTE Positioning Profile Settings
+####################################
+# LPP_PROFILE is a bit mask
+# 0: Enable RRLP on LTE(Default)
+# 0x1: LPP User Plane
+# 0x2: LPP Control Plane
+# 0x4: LPP User Plane for NR5G
+# 0x8: LPP Control Plane for NR5G
+LPP_PROFILE = 2
+
+####################################
+#Datum Type
+####################################
+# 0: WGS-84
+# 1: PZ-90
+DATUM_TYPE = 0
+
+################################
+# EXTRA SETTINGS
+################################
+# NMEA provider (1=Modem Processor, 0=Application Processor)
+NMEA_PROVIDER=0
+
+################################
+# NMEA TAG BLOCK GROUPING
+################################
+# NMEA tag block grouping is only applicable to GSA
+# Default is disabled
+# 0 - disabled
+# 1 - enabled
+NMEA_TAG_BLOCK_GROUPING_ENABLED = 0
+
+# Customized NMEA GGA fix quality that can be used to tell
+# whether SENSOR contributed to the fix.
+#
+# When this configuration item is not enabled (set to any value that is not 1),
+# GGA fix quality conforms to NMEA standard spec as below:
+# PPP/DGNSS/SBAS correction fix w/ or w/o sensor: 2
+# RTK fixed fix w/ or w/o sensor: 4
+# RTK float fix w/ or w/o sensor: 5
+# SPE fix w/ or w/o sensor: 1
+# Sensor dead reckoning fix: 6
+#
+# When this configuration is enabled (set to 1), GGA fix quality
+# will be output as below:
+# PPP fix w/o sensor: 59, w/ sensor: 69
+# DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62
+# RTK fixed fix w/o sensor: 4, w/ sensor: 64
+# RTK float fix w/o sensor: 5, w/ sensor: 65,
+# SPE fix w/o sensor: 1, and w/ sensor: 61
+# Sensor dead reckoning fix: 6
+#
+# any value that is not 1 - disabled
+# 1 - enabled
+CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0
+
+################################
+# NMEA Reporting Rate Config, valid only when NMEA_PROVIDER is set to "0"
+################################
+# NMEA Reporting Rate
+# Set it to "1HZ" for 1Hz NMEA Reporting
+# Set it to "NHZ" for NHz NMEA Reporting
+#Default : NHZ (overridden by position update rate if set to lower rates)
+NMEA_REPORT_RATE=NHZ
+
+# Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE)
+SGLTE_TARGET=0
+
+##################################################
+# Select Positioning Protocol on A-GLONASS system
+##################################################
+# 0x1: RRC CPlane
+# 0x2: RRLP UPlane
+# 0x4: LLP Uplane
+A_GLONASS_POS_PROTOCOL_SELECT = 0
+
+##################################################
+# Select technology for LPPe Control Plane
+##################################################
+# 0x1: DBH for LPPe CP
+# 0x2: WLAN AP Measurements for LPPe CP
+# 0x4: SRN AP measurement for CP
+# 0x8: Sensor Barometer Measurement LPPe CP
+#LPPE_CP_TECHNOLOGY = 0
+
+##################################################
+# Select technology for LPPe User Plane
+##################################################
+# 0x1: DBH for LPPe UP
+# 0x2: WLAN AP Measurements for LPPe UP
+# 0x4: SRN AP measurement for UP
+# 0x8: Sensor Barometer Measurement LPPe UP
+#LPPE_UP_TECHNOLOGY = 0
+
+##################################################
+# AGPS_CONFIG_INJECT
+##################################################
+# enable/disable injection of AGPS configurations:
+# SUPL_VER
+# SUPL_HOST
+# SUPL_PORT
+# MO_SUPL_HOST
+# MO_SUPL_PORT
+# C2K_HOST
+# C2K_PORT
+# LPP_PROFILE
+# A_GLONASS_POS_PROTOCOL_SELECT
+# 0: disable
+# 1: enable
+AGPS_CONFIG_INJECT = 1
+
+##################################################
+# GNSS settings for automotive use cases
+# Configurations in following section are
+# specific to automotive use cases, others
+# please do not change, keep the default values
+##################################################
+
+# AP Coarse Timestamp Uncertainty
+##################################################
+# default : 10
+# AP time stamp uncertainty, until GNSS receiver
+# is able to acquire better timing information
+AP_TIMESTAMP_UNCERTAINTY = 10
+
+#####################################
+# DR_SYNC Pulse Availability
+#####################################
+# 0 : DR_SYNC pulse not available (default)
+# 1 : DR_SYNC pulse available
+# This configuration enables the driver to make use
+# of PPS events generated by DR_SYNC pulse
+# Standard Linux PPS driver needs to be enabled
+DR_SYNC_ENABLED = 0
+
+#####################################
+# PPS Device name
+#####################################
+PPS_DEVICENAME = /dev/pps0
+
+#####################################
+# Ignore PPS at Startup and after long outage
+#####################################
+IGNORE_PPS_PULSE_COUNT = 1
+
+#####################################
+# Long GNSS RF outage in seconds
+#####################################
+GNSS_OUTAGE_DURATION = 10
+
+#####################################
+# AP Clock Accuracy
+#####################################
+# Quality of APPS processor clock (in PPM).
+# Value specified is used for calculation of
+# APPS time stamp uncertainty
+AP_CLOCK_PPM = 100
+
+#####################################
+# MAX ms difference to detect missing pulse
+#####################################
+# Specifies time threshold in ms to validate any missing PPS pulses
+MISSING_PULSE_TIME_DELTA = 900
+
+#####################################
+# Propagation time uncertainty
+#####################################
+# This settings enables time uncertainty propagation
+# logic incase of missing PPS pulse
+PROPAGATION_TIME_UNCERTAINTY = 1
+
+#######################################
+# APN / IP Type Configuration
+# APN and IP Type to use for setting
+# up WWAN call.
+# Use below values for IP Type:
+# v4 = 4
+# v6 = 6
+# v4v6 = 10
+#######################################
+# INTERNET_APN = abc.xyz
+# INTERNET_IP_TYPE = 4
+# SUPL_APN = abc.xyz
+# SUPL_IP_TYPE = 4
+
+#####################################
+# Modem type
+#####################################
+# This setting configures modem type
+# (external=0 or internal=1)
+# comment out the next line to vote
+# for the first modem in the list
+MODEM_TYPE = 1
+
+##################################################
+# CONSTRAINED TIME UNCERTAINTY MODE
+##################################################
+# 0 : disabled (default)
+# 1 : enabled
+# This setting enables GPS engine to keep its time
+# uncertainty below the specified constraint
+#CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 0
+
+# If constrained time uncertainty mode is enabled,
+# this setting specifies the time uncertainty
+# threshold that gps engine need to maintain.
+# In unit of milli-seconds.
+# Default is 0.0 meaning that modem default value
+# of time uncertainty threshold will be used.
+#CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD = 0.0
+
+# If constrained time uncertainty mode is enabled,
+# this setting specifies the power budget that
+# gps engine is allowed to spend to maintain the time
+# uncertainty.
+# Default is 0 meaning that GPS engine is not constained
+# by power budget and can spend as much power as needed.
+# In unit of 0.1 milli watt second.
+#CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET = 0
+
+##################################################
+# POSITION ASSISTED CLOCK ESTIMATOR
+##################################################
+# 0 : disabled (default)
+# 1 : enabled
+# This setting enables GPS engine to estimate clock
+# bias and drift when the signal from at least 1
+# SV is available and the UE's position is known by
+# other position engines.
+#POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED = 0
+
+#####################################
+# proxyAppPackageName
+#####################################
+# This is a string that is sent to the framework
+# in nfwNotifyCb callback
+PROXY_APP_PACKAGE_NAME = com.google.android.carrierlocation
+
+#####################################
+# CP_MTLR_ES
+#####################################
+# CP MTLR ES, 1=enable, 0=disable
+CP_MTLR_ES=0
+
+##################################################
+# GNSS_DEPLOYMENT
+##################################################
+# 0 : Enable QTI GNSS (default)
+# 1 : Enable QCSR SS5
+# 2 : Enable PDS API
+# This setting use to select between QTI GNSS,
+# QCSR SS5 hardware receiver, and PDS API.
+# By default QTI GNSS receiver is enabled.
+# GNSS_DEPLOYMENT = 0
+
+##################################################
+## LOG BUFFER CONFIGURATION
+##################################################
+#LOG_BUFFER_ENABLED, 1=enable, 0=disable
+#*_LEVEL_TIME_DEPTH, maximum time depth of level *
+#in log buffer, unit is second
+#*_LEVEL_MAX_CAPACITY, maximum numbers of level *
+#log print sentences in log buffer
+LOG_BUFFER_ENABLED = 0
+E_LEVEL_TIME_DEPTH = 600
+E_LEVEL_MAX_CAPACITY = 50
+W_LEVEL_TIME_DEPTH = 500
+W_LEVEL_MAX_CAPACITY = 100
+I_LEVEL_TIME_DEPTH = 400
+I_LEVEL_MAX_CAPACITY = 200
+D_LEVEL_TIME_DEPTH = 30
+D_LEVEL_MAX_CAPACITY = 300
+V_LEVEL_TIME_DEPTH = 200
+V_LEVEL_MAX_CAPACITY = 400
+
+##################################################
+# Allow buffer diag log packets when diag memory allocation
+# fails during boot up time.
+##################################################
+BUFFER_DIAG_LOGGING = 1
+
+#######################################
+# NTRIP CLIENT LIBRARY NAME
+#######################################
+# NTRIP_CLIENT_LIB_NAME =
+
+##################################################
+# Correction Data Framework settings
+# Default values:
+# CDFW_SOURCE_PRIORITY_1 = INTERNAL_1 RTCM
+# CDFW_INJECT_DATA_INTERVAL = 600000 //10 mins
+# CDFW_RTCM_MESSAGE_INTERVAL = 1000 //1 second
+#
+# If multiple sources coexist on a PL,
+# the prorioty sequence can be set by the integer number.
+# PRIORITY_1 is higher than PRIORITY_2, for example,
+# CDFW_SOURCE_PRIORITY_1 = INTERNAL_1 RTCM
+# CDFW_SOURCE_PRIORITY_2 = CV2X RTCM
+##################################################
+
+##################################################
+# RF LOSS
+# The loss in 0.1 dbHz from the C/N0 at the antenna port
+# These values must be configured by OEM if not
+# supported in QMI LOC message
+# There is one entry for each signal type
+##################################################
+RF_LOSS_GPS = 0
+RF_LOSS_GPS_L5 = 0
+RF_LOSS_GLO_LEFT = 0
+RF_LOSS_GLO_CENTER = 0
+RF_LOSS_GLO_RIGHT = 0
+RF_LOSS_BDS = 0
+RF_LOSS_BDS_B2A = 0
+RF_LOSS_GAL = 0
+RF_LOSS_GAL_E5 = 0
+RF_LOSS_NAVIC = 0
diff --git a/gps/etc/izat.conf b/gps/etc/izat.conf
new file mode 100644
index 0000000..e891154
--- /dev/null
+++ b/gps/etc/izat.conf
@@ -0,0 +1,277 @@
+#########################################
+# Log verbosity control for izat modules
+#########################################
+# OFF = 0, ERROR = 1, WARNING = 2, INFO = 3, DEBUG = 4, VERBOSE = 5
+IZAT_DEBUG_LEVEL = 2
+
+##################################################
+# Select WIFI Wait Timeout value in seconds for SUPL
+##################################################
+WIFI_WAIT_TIMEOUT_SELECT = 0
+
+##################################################
+# Time interval of injecting SRN scan data to modem
+# time in seconds.
+# Note: recommended value is between 1-5 sec
+##################################################
+LPPE_SRN_DATA_SCAN_INJECT_TIME=2
+
+################################
+# NLP Settings
+################################
+# NLP_MODE 1: OSNLP Only, 2: QNP Only, 3: Combo, 4: QNP preferred
+# For Automotive products, please use NLP_MODE = 4 only.
+# NLP_TOLERANCE_TIME_FIRST: Time in ms used in Combo mode
+# to determine how much Tolerance for first position
+# NLP_TOLERANCE_TIME_AFTER: Time in ms used in Combo mode
+# to determine how much Tolerance for positions after first
+# NLP_THRESHOLD: Sets how many failures needed before
+# switching preferred NLP in Combo mode
+# NLP_ACCURACY_MULTIPLE: Determines how far off the accuracy
+# must be, in multiples, between two NLP location reports to
+# be considered much worse accuracy. Used in switching logic
+# NLP COMBO MODE USES QNP WITH NO EULA CONSENT: Determines
+# whether or not to still send network location requests to
+# QNP when the EULA is not consented to by the user. QNP can
+# still return ZPP locations or injected locations even
+# without EULA consent, but the uncertainty can be high.
+# QNP preferred mode prefers QNP when there is EULA consent,
+# otherwise OSNLP is used.
+NLP_MODE = 1
+NLP_MODE_EMERGENCY = 2
+NLP_TOLERANCE_TIME_FIRST = 5000
+NLP_TOLERANCE_TIME_AFTER = 20000
+NLP_THRESHOLD = 3
+NLP_ACCURACY_MULTIPLE = 2
+NLP_COMBO_MODE_USES_QNP_WITH_NO_EULA_CONSENT = 1
+
+#########################################
+# NLP PACKAGE SETTINGS
+#########################################
+# OSNLP_PACKAGE: name of default NLP package
+OSNLP_PACKAGE = com.google.android.gms
+# REGION_OSNLP_PACKAGE:
+# This value will be used as alternative
+# for particular region where default NLP is not functional.
+#REGION_OSNLP_PACKAGE =
+
+###################################
+# GEOFENCE SERVICES
+###################################
+# If set to one of the defined values below, it will override
+# the responsiveness for geofence services, which implements
+# the Proximity Alert API. If not set to a value defined below,
+# which is default, it will not override the responsivness.
+# The geofence HAL API is unaffected by this value.
+# GEOFENCE_SERVICES_RESPONSIVENESS_OVERRIDE Values:
+# 1: LOW responsiveness
+# 2: MEDIUM responsiveness
+# 3: HIGH responsiveness
+GEOFENCE_SERVICES_RESPONSIVENESS_OVERRIDE = 0
+
+#####################################
+#GTP Opt-In app
+#####################################
+
+#GTP privacy policy version url
+#https support is required
+GTP_PRIVACY_VERSION_URL = https://info.izatcloud.net/privacy/version.html
+
+#GTP privacy policy version download retry interval
+#unit is second. default is 86400
+GTP_PRIVACY_RETRY_INTERVAL = 86400
+
+#####################################
+# IZAT PREMIUM FEATURE SETTINGS
+#####################################
+#Possible states of a feature:
+#DISABLED
+#BASIC
+#PREMIUM
+
+#GTP_MODE valid modes:
+# DISABLED
+# LEGACY_WWAN
+# SDK (WWAN not available for Modems before LocTech 10.0)
+# SDK_WIFI (WWAN provided by legacy Modem)
+GTP_MODE=DISABLED
+
+#GTP_WAA valid modes:
+# DISABLED
+# BASIC
+GTP_WAA=DISABLED
+
+#SAP valid modes:
+# DISABLED
+# BASIC
+# PREMIUM
+# PREMIUM_ENV_AIDING
+# MODEM_DEFAULT
+SAP=PREMIUM
+
+#FREE_WIFI_SCAN_INJECT valid modes:
+#DISABLED
+#BASIC
+FREE_WIFI_SCAN_INJECT=BASIC
+
+#SUPL_WIFI valid modes:
+#DISABLED
+#BASIC
+SUPL_WIFI=BASIC
+
+#WIFI_SUPPLICANT_INFO valid modes:
+#DISABLED
+#BASIC
+WIFI_SUPPLICANT_INFO=BASIC
+
+#####################################
+# Location process launcher settings
+#####################################
+
+# DO NOT MODIFY
+# Modifying below attributes without
+# caution can have serious implications.
+
+#Values for PROCESS_STATE:
+# ENABLED
+# DISABLED
+
+#Values for LOW_RAM_TARGETS:
+# ENABLED
+# DISABLED
+# Property to enable/disable processes for low ram targets. Uses ro.config.low_ram property
+# to identify low ram targets.
+
+#PROCESS_NAME
+# Name of the executable file.
+
+#FEATURE MASKS:
+# GTP-WIFI 0X03
+# GTP-MP-CELL 0xc00
+# GTP-WAA 0x100
+# SAP 0Xc0
+# ODCPI 0x1000
+# FREE_WIFI_SCAN_INJECT 0x2000
+# SUPL_WIFI 0x4000
+# WIFI_SUPPLICANT_INFO 0x8000
+
+#Values for PLATFORMS can be:
+#1. Any valid values obtained from ro.board.platform separated by single space. For example: msm8960 msm8226
+#2. 'all' or 'all exclude' -> for All platforms
+#3. 'all exclude XXXX' -> All platforms exclude XXXX. For example: all exclude msm8937
+
+#Values for SOC_IDS can be:
+#1. Any valid values obtained from soc_id node separated by single space. For example: 339 386 436
+## soc_id value can be obtained from any one of below node:
+## - /sys/devices/soc0/soc_id
+## - /sys/devices/system/soc/soc0/id
+#2. 'all' or 'all exclude' -> for All soc id's
+#3. 'all exclude XXXX' -> All soc id's exclude XXXX. For example: all exclude 339 386
+
+#Values for BASEBAND can be:
+#1. Any valid values obtained from ro.baseband separated by single space. For example: sglte sglte2
+#2. 'all' or 'all exclude' -> for all basebands
+#3. 'all exclude XXXX' -> All basebands exclude XXXX. For example: all exclude sglte
+PROCESS_NAME=lowi-server
+PROCESS_ARGUMENT=
+PROCESS_STATE=DISABLED
+PROCESS_GROUPS=gps wifi inet oem_2901
+PREMIUM_FEATURE=0
+IZAT_FEATURE_MASK=0xf303
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=ENABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=0
+
+PROCESS_NAME=xtwifi-inet-agent
+PROCESS_ARGUMENT=
+PROCESS_STATE=DISABLED
+PROCESS_GROUPS=inet gps
+PREMIUM_FEATURE=1
+IZAT_FEATURE_MASK=0xc03
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=ENABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=1
+
+PROCESS_NAME=xtwifi-client
+PROCESS_ARGUMENT=
+PROCESS_STATE=DISABLED
+PROCESS_GROUPS=wifi inet gps system oem_2904
+PREMIUM_FEATURE=1
+IZAT_FEATURE_MASK=0xd03
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=ENABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=1
+
+PROCESS_NAME=slim_daemon
+PROCESS_ARGUMENT=
+PROCESS_STATE=ENABLED
+PROCESS_GROUPS=gps oem_2901 can plugdev diag sensors
+PREMIUM_FEATURE=1
+IZAT_FEATURE_MASK=0xf0
+PLATFORMS=all
+SOC_IDS=all exclude 386 436
+BASEBAND=all
+LOW_RAM_TARGETS=DISABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=1
+
+PROCESS_NAME=xtra-daemon
+PROCESS_ARGUMENT=
+PROCESS_STATE=ENABLED
+PROCESS_GROUPS=inet gps system
+PREMIUM_FEATURE=0
+IZAT_FEATURE_MASK=0
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=ENABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=0
+
+########################################
+# Engine Service which host DRE module #
+# To enable DRE engine service, change #
+# PROCESS_STATE=ENABLED #
+########################################
+PROCESS_NAME=engine-service
+PROCESS_ARGUMENT=DRE-INT libloc_epDr.so
+PROCESS_STATE=DISABLED
+PROCESS_GROUPS=gps diag inet qwes oem_2901 system
+PREMIUM_FEATURE=0
+IZAT_FEATURE_MASK=0
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=DISABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=1
+
+########################################
+# Engine Service which host PPE module #
+# To enable PPE engine service, change #
+# PROCESS_STATE=ENABLED #
+# and update process arugements #
+# with PPE library name #
+#PROCESS_ARGUMENT=PPE libepsimulator.so#
+########################################
+PROCESS_NAME=engine-service
+PROCESS_ARGUMENT=PPE libepsimulator.so
+PROCESS_STATE=DISABLED
+PROCESS_GROUPS=gps diag inet qwes oem_2901 system
+PREMIUM_FEATURE=0
+IZAT_FEATURE_MASK=0
+PLATFORMS=all
+SOC_IDS=all
+BASEBAND=all
+LOW_RAM_TARGETS=DISABLED
+HARDWARE_TYPE=all
+VENDOR_ENHANCED_PROCESS=1
diff --git a/gps/etc/lowi.conf b/gps/etc/lowi.conf
new file mode 100644
index 0000000..ff7611d
--- /dev/null
+++ b/gps/etc/lowi.conf
@@ -0,0 +1,26 @@
+#*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+#
+# LOWI Config file - default
+#
+# GENERAL DESCRIPTION
+# This file contains the config params for LOWI
+#
+# Copyright (c) 2019 Qualcomm Technologies, Inc.
+# All Rights Reserved.
+# Confidential and Proprietary - Qualcomm Technologies, Inc.
+#
+# 2012-2013 Qualcomm Atheros, Inc.
+# All Rights Reserved.
+# Qualcomm Atheros Confidential and Proprietary.
+#
+# Export of this technology or software is regulated by the U.S. Government.
+# Diversion contrary to U.S. law prohibited.
+#=============================================================================*/
+
+# X86 ONLY - UBUNTU:
+# Copy this file in the same directory where the executable is
+
+# Log level
+# EL_LOG_OFF = 0, EL_ERROR = 1, EL_WARNING = 2, EL_INFO = 3, EL_DEBUG = 4, EL_VERBOSE = 5, EL_LOG_ALL = 100
+LOWI_LOG_LEVEL = 4
+LOWI_USE_LOWI_LP = 0
diff --git a/gps/etc/sap.conf b/gps/etc/sap.conf
new file mode 100644
index 0000000..ce1d088
--- /dev/null
+++ b/gps/etc/sap.conf
@@ -0,0 +1,181 @@
+################################
+# Sensor Settings
+################################
+#The following parameters are optional.
+#Internal defaults support MEMS sensors
+#native to most handset devices.
+#Device specific sensor characterization
+#for improved performance is possible as
+#described in SAP application notes.
+#GYRO_BIAS_RANDOM_WALK=
+#ACCEL_RANDOM_WALK_SPECTRAL_DENSITY=
+#ANGLE_RANDOM_WALK_SPECTRAL_DENSITY=
+#RATE_RANDOM_WALK_SPECTRAL_DENSITY=
+#VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY=
+
+# DEBUG LEVELS: 0 - none, 1 - Error, 2 - Warning, 3 - Info
+# 4 - Debug, 5 - Verbose
+# If DEBUG_LEVEL is commented, Android's logging levels will be used
+DEBUG_LEVEL = 0
+# Sensor Sampling Rate Parameters for Low-Data Rate Filter (should be greater than 0)
+# used in loc_eng_reinit
+SENSOR_ACCEL_BATCHES_PER_SEC=2
+SENSOR_ACCEL_SAMPLES_PER_BATCH=5
+SENSOR_GYRO_BATCHES_PER_SEC=2
+SENSOR_GYRO_SAMPLES_PER_BATCH=5
+# Sensor Sampling Rate Parameters for High-Data Rate Filter (should be greater than 0)
+SENSOR_ACCEL_BATCHES_PER_SEC_HIGH=4
+SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH=25
+SENSOR_GYRO_BATCHES_PER_SEC_HIGH=4
+SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH=25
+
+# Sensor Control Mode (0=AUTO, 1=FORCE_ON, 2=MODEM_DEFAULT)
+# used in loc_eng_reinit
+SENSOR_CONTROL_MODE=1
+SENSOR_USAGE= 0
+SENSOR_PROVIDER= 1
+
+# Bit mask used to define which sensor algorithms are used.
+# Setting each bit has the following definition:
+# 0x1 - DISABLE_INS_POSITIONING_FILTER
+# 0x0 - ENABLE_INS_POSITIONING_FILTER
+SENSOR_ALGORITHM_CONFIG_MASK=0x0
+
+#Vehicle Network Provider configuration
+
+#Service configuration strings
+#The number before colon in VN_X items defines version of the format of the rest of the string
+#VN_ACCEL_CFG=0:5
+#VN_GYRO_CFG=0:5.5
+#VN_ODOMETRY_CFG=0:2,4.5
+
+################################################
+# QDR3 configurations #
+################################################
+#VN_SPEED_CFG=1:131,5,8,1,2,3,1,1,9,2,14,2
+#VN_GEAR_CFG=1:422,20,4,0,4,1,9,0,1,2,3,4,5,6,7,8
+VN_SPEED_CFG=1:777,0,0,1,3,1,0.002778,0,40,8,32,8
+VN_GEAR_CFG=1:422,20,4,0,4,1,9,0,1,2,3,4,5,6,7,8
+
+################################################
+# QDR2-Gyro configurations #
+################################################
+#VN_GYRO_CFG=1:555,0,1,0,0,0,0,-6.5,6.6066,-6.5,-1.00,2,6.607,6.6068,0,0,16,0.0002,0,16,0.0002,0,16,0.0002
+#VN_SPEED_CFG=1:555,0,0,1,2,1,0.01,0,56,8,48,8
+#VN_GEAR_CFG=1:555,16,4,0,1,1,9,0,1,2,3,4,5,6,7,8
+
+################################################
+# QDR2-DWT configurations #
+################################################
+#VN_SPEED_CFG=1:555,22,1,2,1,1,1,0,8,8,23,1,2,0,1,0,8,8,23,1
+#VN_GEAR_CFG=1:555,12,4,16,14,16,8,1,2,3,4,5,6,7,8
+#VN_DWS_CFG=1:555,0,0,1,3,1,1,0,0,8,0,0,8,8,0,0,16,8,0,0,24,8,0,0
+#VN_GYRO_CFG=1:555,40,16,1.0,40,16,1.0,40,16,1.0
+
+#####################################################################################
+# VNW service batching configuration strings #
+# VNW provider will initialize default type as Time based batching #
+# Each service batch value is configured to be 100 #
+# VN_ACCEL_CFG_BATCH_VALUE will be treated as time in Ms if VN_CFG_BATCH_TYPE #
+# is set to time based batching #
+# VN_ACCEL_CFG_BATCH_VALUE will be treated as sample count if VN_CFG_BATCH_TYPE #
+# is set to count based batching #
+# Uncomment and update batch time /sample count as per selected batching type #
+#####################################################################################
+# Batching type
+# 1 - Time based (default)
+# 2 - Count based
+VN_CFG_BATCH_TYPE=1
+
+#Vehicle Accel batching value, it can either accept time in milli seconds or sample count
+#VN_ACCEL_CFG_BATCH_VALUE=100
+
+#Vehicle Gyro batching value, it can either accept time in milli seconds or sample count
+VN_GYRO_CFG_BATCH_VALUE=50
+
+#Vehicle Odo batching value, it can either accept time in milli seconds or sample count
+#VN_ODOMETRY_CFG_BATCH_VALUE=100
+
+#Vehicle Speed batching value, it can either accept time in milli seconds or sample count
+VN_SPEED_CFG_BATCH_VALUE=50
+
+#Vehicle Gear batching value, it can either accept time in milli seconds or sample count
+VN_GEAR_CFG_BATCH_VALUE=50
+
+#Vehicle DWS batching value, it can either accept time in milli seconds or sample count
+#VN_DWS_CFG_BATCH_VALUE=100
+####################################################################################
+
+#Procesors clock ratio: AP and CAN bus microcontroller
+################################################
+# QDR3 configurations #
+################################################
+VN_PROC_CLOCK_RATIO=1.0
+
+################################################
+# QDR2-DWT OR QDR2-Gyro configurations #
+################################################
+#VN_PROC_CLOCK_RATIO = 1.0
+
+# Time source used by Sensor HAL
+# Setting this value controls accuracy of location sensor services.
+# 0 - Unknown
+# 1 - CLOCK_BOOTTIME
+# 2 - CLOCK_MONOTONIC
+# 3 - CLOCK_REALTIME
+# 4 - CLOCK_BOOTTIME using Alarm timer interface
+NDK_PROVIDER_TIME_SOURCE=1
+
+# Sensor Batching Configuration
+# 0 - Time based
+# 1 - Fixed count based
+# 2 - Variable count based
+COUNT_BASED_BATCHING=1
+SYNC_ONCE=0
+
+# Vehicle Network Data optimization
+# Default value: 0
+# Value 0x40000 - Speed(bit 18 eSLIM_SERVICE_VEHICLE_SPEED)
+# Value 0x80000 - Speed(bit 19 eSLIM_SERVICE_VEHICLE_DWS)
+# Value 0x100000 - Speed(bit 20 eSLIM_SERVICE_VEHICLE_GEAR)
+VN_ENABLE_DATA_OPTIMIZATION=0x100000
+
+# Vehicle Network Data Routing time interval
+# This is applicable only if VN_ENABLE_DATA_OPTIMIZATION value is set
+# Default value: 5000 msec
+VN_DATA_ROUTING_TIME_INTERVAL_MSEC=3000
+
+#Sensor HAL Provider Configuration HAL Library name including path
+################################################
+# #
+# Configuration for BMI 160 Sensor #
+# #
+################################################
+#SENSOR_TYPE=2
+#SENSOR_HAL_LIB_PATH=/usr/lib/libbmi160sensors.so.1
+
+################################################
+# #
+# Configuration for ASM330 Sensor #
+# #
+################################################
+SENSOR_TYPE=1
+SENSOR_HAL_LIB_PATH=/usr/lib/libasm330sensors.so.1
+
+
+################################################
+# #
+# Configuration for IAM20680 Sensor #
+# #
+################################################
+#SENSOR_TYPE=3
+#SENSOR_HAL_LIB_PATH=/usr/lib/libiam20680sensors.so.1
+
+
+################################################
+# #
+# Configuration for SMI130 Sensor #
+# #
+################################################
+#SENSOR_TYPE=4
+#SENSOR_HAL_LIB_PATH=/usr/lib/libsmi130sensors.so.1
diff --git a/gps/etc/seccomp_policy/gnss@2.0-base.policy b/gps/etc/seccomp_policy/gnss@2.0-base.policy
new file mode 100644
index 0000000..7b93037
--- /dev/null
+++ b/gps/etc/seccomp_policy/gnss@2.0-base.policy
@@ -0,0 +1,95 @@
+#*******************************************************************************
+# Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of The Linux Foundation, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+
+clone: 1
+close: 1
+connect: 1
+execve: 1
+exit_group: 1
+exit: 1
+faccessat: 1
+fcntl: 1
+fstat: 1
+fstatfs: 1
+futex: 1
+getpid: 1
+getuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+geteuid: 1
+umask: 1
+getrandom: 1
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mremap: 1
+munmap: 1
+newfstatat: 1
+openat: 1
+#prctl: arg0 == PR_SET_VMA || arg0 == PR_SET_NO_NEW_PRIVS || arg0 == PR_GET_DUMPABLE || arg0 == PR_SET_SECCOMP || arg0 == 0x37 /* PR_??? */
+prctl: 1
+pread64: 1
+read: 1
+pwrite64: 1
+write: 1
+writev: 1
+readlinkat: 1
+restart_syscall: 1
+rt_sigaction: 1
+rt_sigprocmask: 1
+rt_sigreturn: 1
+sched_getscheduler: 1
+set_tid_address: 1
+sigaltstack: 1
+unlinkat: 1
+lseek: 1
+##ioctl: arg1 == _IOC(_IOC_NONE || arg1 == _IOC(_IOC_READ || arg1 == VSOC_MAYBE_SEND_INTERRUPT_TO_HOST
+ioctl: 1
+clock_gettime: 1
+
+
+socket: arg0 == AF_INET6 || arg0 == AF_UNIX || arg0 == AF_QIPCRTR
+connect: 1
+setsockopt: 1
+getsockname: 1
+socketpair: 1
+ppoll: 1
+pselect6: 1
+accept4: 1
+listen: 1
+bind: 1
+pipe2: 1
+
+recvmsg: 1
+sendmsg: 1
+
+sendto: 1
+recvfrom: 1
+
diff --git a/gps/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy b/gps/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy
new file mode 100644
index 0000000..19b67bb
--- /dev/null
+++ b/gps/etc/seccomp_policy/gnss@2.0-xtra-daemon.policy
@@ -0,0 +1,48 @@
+#*******************************************************************************
+# Copyright (c) 2020 The Linux Foundation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of The Linux Foundation, nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#******************************************************************************
+bind: 1
+getrlimit: 1
+
+pipe2: 1
+
+sched_getaffinity: 1
+timerfd_create: 1
+unlinkat: 1
+setpriority: 1
+
+epoll_create1: 1
+epoll_ctl: 1
+epoll_pwait: 1
+timerfd_settime: 1
+
+fdatasync: 1
+madvise: 1
+ftruncate: 1
+
diff --git a/gps/geofence/Android.bp b/gps/geofence/Android.bp
new file mode 100644
index 0000000..4801eb8
--- /dev/null
+++ b/gps/geofence/Android.bp
@@ -0,0 +1,31 @@
+
+
+cc_library_shared {
+
+ name: "libgeofencing",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ srcs: [
+ "GeofenceAdapter.cpp",
+ "location_geofence.cpp",
+ ],
+
+ shared_libs: [
+ "libutils",
+ "libcutils",
+ "libgps.utils",
+ "liblog",
+ "libloc_core",
+ ],
+
+ header_libs: [
+ "libgps.utils_headers",
+ "libloc_core_headers",
+ "libloc_pla_headers",
+ "liblocation_api_headers",
+ ],
+
+ cflags: GNSS_CFLAGS,
+}
diff --git a/gps/geofence/GeofenceAdapter.cpp b/gps/geofence/GeofenceAdapter.cpp
new file mode 100644
index 0000000..f024e3f
--- /dev/null
+++ b/gps/geofence/GeofenceAdapter.cpp
@@ -0,0 +1,866 @@
+/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_GeofenceAdapter"
+
+#include <GeofenceAdapter.h>
+#include "loc_log.h"
+#include <log_util.h>
+#include <string>
+
+using namespace loc_core;
+
+GeofenceAdapter::GeofenceAdapter() :
+ LocAdapterBase(0,
+ LocContext::getLocContext(LocContext::mLocationHalName),
+ true /*isMaster*/)
+{
+ LOC_LOGD("%s]: Constructor", __func__);
+}
+
+void
+GeofenceAdapter::stopClientSessions(LocationAPI* client)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+
+ for (auto it = mGeofenceIds.begin(); it != mGeofenceIds.end();) {
+ uint32_t hwId = it->second;
+ GeofenceKey key(it->first);
+ if (client == key.client) {
+ it = mGeofenceIds.erase(it);
+ mLocApi->removeGeofence(hwId, key.id,
+ new LocApiResponse(*getContext(),
+ [this, hwId] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ auto it2 = mGeofences.find(hwId);
+ if (it2 != mGeofences.end()) {
+ mGeofences.erase(it2);
+ } else {
+ LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId);
+ }
+ }
+ }));
+ continue;
+ }
+ ++it; // increment only when not erasing an iterator
+ }
+
+}
+
+void
+GeofenceAdapter::updateClientsEventMask()
+{
+ LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (it->second.geofenceBreachCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT;
+ mask |= LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL;
+ }
+ if (it->second.geofenceStatusCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT;
+ }
+ }
+ updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
+}
+
+LocationError
+GeofenceAdapter::getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId)
+{
+ GeofenceKey key(client, clientId);
+ auto it = mGeofenceIds.find(key);
+ if (it != mGeofenceIds.end()) {
+ hwId = it->second;
+ return LOCATION_ERROR_SUCCESS;
+ }
+ return LOCATION_ERROR_ID_UNKNOWN;
+}
+
+LocationError
+GeofenceAdapter::getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key)
+{
+ auto it = mGeofences.find(hwId);
+ if (it != mGeofences.end()) {
+ key = it->second.key;
+ return LOCATION_ERROR_SUCCESS;
+ }
+ return LOCATION_ERROR_ID_UNKNOWN;
+}
+
+void
+GeofenceAdapter::handleEngineUpEvent()
+{
+ struct MsgSSREvent : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ inline MsgSSREvent(GeofenceAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ virtual void proc() const {
+ mAdapter.setEngineCapabilitiesKnown(true);
+ mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+ mAdapter.restartGeofences();
+ for (auto msg: mAdapter.mPendingMsgs) {
+ mAdapter.sendMsg(msg);
+ }
+ mAdapter.mPendingMsgs.clear();
+ }
+ };
+
+ sendMsg(new MsgSSREvent(*this));
+}
+
+void
+GeofenceAdapter::restartGeofences()
+{
+ if (mGeofences.empty()) {
+ return;
+ }
+
+ GeofencesMap oldGeofences(mGeofences);
+ mGeofences.clear();
+ mGeofenceIds.clear();
+
+ for (auto it = oldGeofences.begin(); it != oldGeofences.end(); it++) {
+ GeofenceObject object = it->second;
+ GeofenceOption options = {sizeof(GeofenceOption),
+ object.breachMask,
+ object.responsiveness,
+ object.dwellTime};
+ GeofenceInfo info = {sizeof(GeofenceInfo),
+ object.latitude,
+ object.longitude,
+ object.radius};
+ mLocApi->addGeofence(object.key.id,
+ options,
+ info,
+ new LocApiResponseData<LocApiGeofenceData>(*getContext(),
+ [this, object, options, info] (LocationError err, LocApiGeofenceData data) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (true == object.paused) {
+ mLocApi->pauseGeofence(data.hwId, object.key.id,
+ new LocApiResponse(*getContext(), [] (LocationError err ) {}));
+ }
+ saveGeofenceItem(object.key.client, object.key.id, data.hwId, options, info);
+ }
+ }));
+ }
+}
+
+void
+GeofenceAdapter::reportResponse(LocationAPI* client, size_t count, LocationError* errs,
+ uint32_t* ids)
+{
+ IF_LOC_LOGD {
+ std::string idsString = "[";
+ std::string errsString = "[";
+ if (NULL != ids && NULL != errs) {
+ for (size_t i=0; i < count; ++i) {
+ idsString += std::to_string(ids[i]) + " ";
+ errsString += std::to_string(errs[i]) + " ";
+ }
+ }
+ idsString += "]";
+ errsString += "]";
+
+ LOC_LOGD("%s]: client %p ids %s errs %s",
+ __func__, client, idsString.c_str(), errsString.c_str());
+ }
+
+ auto it = mClientData.find(client);
+ if (it != mClientData.end() && it->second.collectiveResponseCb != nullptr) {
+ it->second.collectiveResponseCb(count, errs, ids);
+ } else {
+ LOC_LOGE("%s]: client %p response not found in info", __func__, client);
+ }
+}
+
+uint32_t*
+GeofenceAdapter::addGeofencesCommand(LocationAPI* client, size_t count, GeofenceOption* options,
+ GeofenceInfo* infos)
+{
+ LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
+
+ struct MsgAddGeofences : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ size_t mCount;
+ uint32_t* mIds;
+ GeofenceOption* mOptions;
+ GeofenceInfo* mInfos;
+ inline MsgAddGeofences(GeofenceAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ size_t count,
+ uint32_t* ids,
+ GeofenceOption* options,
+ GeofenceInfo* infos) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mCount(count),
+ mIds(ids),
+ mOptions(options),
+ mInfos(infos) {}
+ inline virtual void proc() const {
+ LocationError* errs = new LocationError[mCount];
+ if (nullptr == errs) {
+ LOC_LOGE("%s]: new failed to allocate errs", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ if (NULL == mIds || NULL == mOptions || NULL == mInfos) {
+ errs[i] = LOCATION_ERROR_INVALID_PARAMETER;
+ } else {
+ mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient,
+ mOptions = mOptions, mInfos = mInfos, mIds = mIds, &mApi = mApi,
+ errs, i] (LocationError err ) {
+ mApi.addGeofence(mIds[i], mOptions[i], mInfos[i],
+ new LocApiResponseData<LocApiGeofenceData>(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mOptions = mOptions, mClient = mClient,
+ mCount = mCount, mIds = mIds, mInfos = mInfos, errs, i]
+ (LocationError err, LocApiGeofenceData data) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mAdapter.saveGeofenceItem(mClient,
+ mIds[i],
+ data.hwId,
+ mOptions[i],
+ mInfos[i]);
+ }
+ errs[i] = err;
+
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ delete[] mOptions;
+ delete[] mInfos;
+ }
+ }));
+ }));
+ }
+ }
+ }
+ };
+
+ if (0 == count) {
+ return NULL;
+ }
+ uint32_t* ids = new uint32_t[count];
+ if (nullptr == ids) {
+ LOC_LOGE("%s]: new failed to allocate ids", __func__);
+ return NULL;
+ }
+ if (NULL != ids) {
+ for (size_t i=0; i < count; ++i) {
+ ids[i] = generateSessionId();
+ }
+ }
+ GeofenceOption* optionsCopy;
+ if (options == NULL) {
+ optionsCopy = NULL;
+ } else {
+ optionsCopy = new GeofenceOption[count];
+ if (nullptr == optionsCopy) {
+ LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__);
+ return NULL;
+ }
+ COPY_IF_NOT_NULL(optionsCopy, options, count);
+ }
+ GeofenceInfo* infosCopy;
+ if (infos == NULL) {
+ infosCopy = NULL;
+ } else {
+ infosCopy = new GeofenceInfo[count];
+ if (nullptr == infosCopy) {
+ LOC_LOGE("%s]: new failed to allocate infosCopy", __func__);
+ return NULL;
+ }
+ COPY_IF_NOT_NULL(infosCopy, infos, count);
+ }
+
+ sendMsg(new MsgAddGeofences(*this, *mLocApi, client, count, ids, optionsCopy, infosCopy));
+ return ids;
+}
+
+void
+GeofenceAdapter::removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
+
+ struct MsgRemoveGeofences : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ size_t mCount;
+ uint32_t* mIds;
+ inline MsgRemoveGeofences(GeofenceAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ size_t count,
+ uint32_t* ids) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mCount(count),
+ mIds(ids) {}
+ inline virtual void proc() const {
+ LocationError* errs = new LocationError[mCount];
+ if (nullptr == errs) {
+ LOC_LOGE("%s]: new failed to allocate errs", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ &mApi = mApi, errs, i] (LocationError err ) {
+ uint32_t hwId = 0;
+ errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
+ if (LOCATION_ERROR_SUCCESS == errs[i]) {
+ mApi.removeGeofence(hwId, mIds[i],
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ hwId, errs, i] (LocationError err ) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mAdapter.removeGeofenceItem(hwId);
+ }
+ errs[i] = err;
+
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }));
+ } else {
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }
+ }));
+ }
+ }
+ };
+
+ if (0 == count) {
+ return;
+ }
+ uint32_t* idsCopy = new uint32_t[count];
+ if (nullptr == idsCopy) {
+ LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(idsCopy, ids, count);
+ sendMsg(new MsgRemoveGeofences(*this, *mLocApi, client, count, idsCopy));
+}
+
+void
+GeofenceAdapter::pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
+
+ struct MsgPauseGeofences : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ size_t mCount;
+ uint32_t* mIds;
+ inline MsgPauseGeofences(GeofenceAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ size_t count,
+ uint32_t* ids) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mCount(count),
+ mIds(ids) {}
+ inline virtual void proc() const {
+ LocationError* errs = new LocationError[mCount];
+ if (nullptr == errs) {
+ LOC_LOGE("%s]: new failed to allocate errs", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ &mApi = mApi, errs, i] (LocationError err ) {
+ uint32_t hwId = 0;
+ errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
+ if (LOCATION_ERROR_SUCCESS == errs[i]) {
+ mApi.pauseGeofence(hwId, mIds[i], new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ hwId, errs, i] (LocationError err ) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mAdapter.pauseGeofenceItem(hwId);
+ }
+ errs[i] = err;
+
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }));
+ } else {
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }
+ }));
+ }
+ }
+ };
+
+ if (0 == count) {
+ return;
+ }
+ uint32_t* idsCopy = new uint32_t[count];
+ if (nullptr == idsCopy) {
+ LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(idsCopy, ids, count);
+ sendMsg(new MsgPauseGeofences(*this, *mLocApi, client, count, idsCopy));
+}
+
+void
+GeofenceAdapter::resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
+
+ struct MsgResumeGeofences : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ size_t mCount;
+ uint32_t* mIds;
+ inline MsgResumeGeofences(GeofenceAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ size_t count,
+ uint32_t* ids) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mCount(count),
+ mIds(ids) {}
+ inline virtual void proc() const {
+ LocationError* errs = new LocationError[mCount];
+ if (nullptr == errs) {
+ LOC_LOGE("%s]: new failed to allocate errs", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ &mApi = mApi, errs, i] (LocationError err ) {
+ uint32_t hwId = 0;
+ errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
+ if (LOCATION_ERROR_SUCCESS == errs[i]) {
+ mApi.resumeGeofence(hwId, mIds[i],
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, hwId,
+ errs, mIds = mIds, i] (LocationError err ) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ errs[i] = err;
+
+ mAdapter.resumeGeofenceItem(hwId);
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }
+ }));
+ } else {
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ }
+ }
+ }));
+ }
+ }
+ };
+
+ if (0 == count) {
+ return;
+ }
+ uint32_t* idsCopy = new uint32_t[count];
+ if (nullptr == idsCopy) {
+ LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(idsCopy, ids, count);
+ sendMsg(new MsgResumeGeofences(*this, *mLocApi, client, count, idsCopy));
+}
+
+void
+GeofenceAdapter::modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids,
+ GeofenceOption* options)
+{
+ LOC_LOGD("%s]: client %p count %zu", __func__, client, count);
+
+ struct MsgModifyGeofences : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ size_t mCount;
+ uint32_t* mIds;
+ GeofenceOption* mOptions;
+ inline MsgModifyGeofences(GeofenceAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ size_t count,
+ uint32_t* ids,
+ GeofenceOption* options) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mCount(count),
+ mIds(ids),
+ mOptions(options) {}
+ inline virtual void proc() const {
+ LocationError* errs = new LocationError[mCount];
+ if (nullptr == errs) {
+ LOC_LOGE("%s]: new failed to allocate errs", __func__);
+ return;
+ }
+ for (size_t i=0; i < mCount; ++i) {
+ if (NULL == mIds || NULL == mOptions) {
+ errs[i] = LOCATION_ERROR_INVALID_PARAMETER;
+ } else {
+ mApi.addToCallQueue(new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient, mIds = mIds,
+ &mApi = mApi, mOptions = mOptions, errs, i] (LocationError err ) {
+ uint32_t hwId = 0;
+ errs[i] = mAdapter.getHwIdFromClient(mClient, mIds[i], hwId);
+ if (LOCATION_ERROR_SUCCESS == errs[i]) {
+ mApi.modifyGeofence(hwId, mIds[i], mOptions[i],
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mCount = mCount, mClient = mClient,
+ mIds = mIds, mOptions = mOptions, hwId, errs, i]
+ (LocationError err ) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ errs[i] = err;
+
+ mAdapter.modifyGeofenceItem(hwId, mOptions[i]);
+ }
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ delete[] mOptions;
+ }
+ }));
+ } else {
+ // Send aggregated response on last item and cleanup
+ if (i == mCount-1) {
+ mAdapter.reportResponse(mClient, mCount, errs, mIds);
+ delete[] errs;
+ delete[] mIds;
+ delete[] mOptions;
+ }
+ }
+ }));
+ }
+ }
+ }
+ };
+
+ if (0 == count) {
+ return;
+ }
+ uint32_t* idsCopy = new uint32_t[count];
+ if (nullptr == idsCopy) {
+ LOC_LOGE("%s]: new failed to allocate idsCopy", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(idsCopy, ids, count);
+ GeofenceOption* optionsCopy;
+ if (options == NULL) {
+ optionsCopy = NULL;
+ } else {
+ optionsCopy = new GeofenceOption[count];
+ if (nullptr == optionsCopy) {
+ LOC_LOGE("%s]: new failed to allocate optionsCopy", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(optionsCopy, options, count);
+ }
+
+ sendMsg(new MsgModifyGeofences(*this, *mLocApi, client, count, idsCopy, optionsCopy));
+}
+
+void
+GeofenceAdapter::saveGeofenceItem(LocationAPI* client, uint32_t clientId, uint32_t hwId,
+ const GeofenceOption& options, const GeofenceInfo& info)
+{
+ LOC_LOGD("%s]: hwId %u client %p clientId %u", __func__, hwId, client, clientId);
+ GeofenceKey key(client, clientId);
+ GeofenceObject object = {key,
+ options.breachTypeMask,
+ options.responsiveness,
+ options.dwellTime,
+ info.latitude,
+ info.longitude,
+ info.radius,
+ false};
+ mGeofences[hwId] = object;
+ mGeofenceIds[key] = hwId;
+ dump();
+}
+
+void
+GeofenceAdapter::removeGeofenceItem(uint32_t hwId)
+{
+ GeofenceKey key;
+ LocationError err = getGeofenceKeyFromHwId(hwId, key);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ LOC_LOGE("%s]: can not find the key for hwId %u", __func__, hwId);
+ } else {
+ auto it1 = mGeofenceIds.find(key);
+ if (it1 != mGeofenceIds.end()) {
+ mGeofenceIds.erase(it1);
+
+ auto it2 = mGeofences.find(hwId);
+ if (it2 != mGeofences.end()) {
+ mGeofences.erase(it2);
+ dump();
+ } else {
+ LOC_LOGE("%s]:geofence item to erase not found. hwId %u", __func__, hwId);
+ }
+ } else {
+ LOC_LOGE("%s]: geofence item to erase not found. hwId %u", __func__, hwId);
+ }
+ }
+}
+
+void
+GeofenceAdapter::pauseGeofenceItem(uint32_t hwId)
+{
+ auto it = mGeofences.find(hwId);
+ if (it != mGeofences.end()) {
+ it->second.paused = true;
+ dump();
+ } else {
+ LOC_LOGE("%s]: geofence item to pause not found. hwId %u", __func__, hwId);
+ }
+}
+
+void
+GeofenceAdapter::resumeGeofenceItem(uint32_t hwId)
+{
+ auto it = mGeofences.find(hwId);
+ if (it != mGeofences.end()) {
+ it->second.paused = false;
+ dump();
+ } else {
+ LOC_LOGE("%s]: geofence item to resume not found. hwId %u", __func__, hwId);
+ }
+}
+
+void
+GeofenceAdapter::modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options)
+{
+ auto it = mGeofences.find(hwId);
+ if (it != mGeofences.end()) {
+ it->second.breachMask = options.breachTypeMask;
+ it->second.responsiveness = options.responsiveness;
+ it->second.dwellTime = options.dwellTime;
+ dump();
+ } else {
+ LOC_LOGE("%s]: geofence item to modify not found. hwId %u", __func__, hwId);
+ }
+}
+
+
+void
+GeofenceAdapter::geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp)
+{
+
+ IF_LOC_LOGD {
+ std::string idsString = "[";
+ if (NULL != hwIds) {
+ for (size_t i=0; i < count; ++i) {
+ idsString += std::to_string(hwIds[i]) + " ";
+ }
+ }
+ idsString += "]";
+ LOC_LOGD("%s]: breachType %u count %zu ids %s",
+ __func__, breachType, count, idsString.c_str());
+ }
+
+ if (0 == count || NULL == hwIds)
+ return;
+
+ struct MsgGeofenceBreach : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ size_t mCount;
+ uint32_t* mHwIds;
+ Location mLocation;
+ GeofenceBreachType mBreachType;
+ uint64_t mTimestamp;
+ inline MsgGeofenceBreach(GeofenceAdapter& adapter,
+ size_t count,
+ uint32_t* hwIds,
+ Location& location,
+ GeofenceBreachType breachType,
+ uint64_t timestamp) :
+ LocMsg(),
+ mAdapter(adapter),
+ mCount(count),
+ mHwIds(new uint32_t[count]),
+ mLocation(location),
+ mBreachType(breachType),
+ mTimestamp(timestamp)
+ {
+ if (nullptr == mHwIds) {
+ LOC_LOGE("%s]: new failed to allocate mHwIds", __func__);
+ return;
+ }
+ COPY_IF_NOT_NULL(mHwIds, hwIds, mCount);
+ }
+ inline virtual ~MsgGeofenceBreach() {
+ delete[] mHwIds;
+ }
+ inline virtual void proc() const {
+ mAdapter.geofenceBreach(mCount, mHwIds, mLocation, mBreachType, mTimestamp);
+ }
+ };
+
+ sendMsg(new MsgGeofenceBreach(*this, count, hwIds, location, breachType, timestamp));
+
+}
+
+void
+GeofenceAdapter::geofenceBreach(size_t count, uint32_t* hwIds, const Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp)
+{
+
+ for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
+ uint32_t* clientIds = new uint32_t[count];
+ if (nullptr == clientIds) {
+ return;
+ }
+ uint32_t index = 0;
+ for (size_t i=0; i < count; ++i) {
+ GeofenceKey key;
+ LocationError err = getGeofenceKeyFromHwId(hwIds[i], key);
+ if (LOCATION_ERROR_SUCCESS == err) {
+ if (key.client == it->first) {
+ clientIds[index++] = key.id;
+ }
+ }
+ }
+ if (index > 0 && it->second.geofenceBreachCb != nullptr) {
+ GeofenceBreachNotification notify = {sizeof(GeofenceBreachNotification),
+ index,
+ clientIds,
+ location,
+ breachType,
+ timestamp};
+
+ it->second.geofenceBreachCb(notify);
+ }
+ delete[] clientIds;
+ }
+}
+
+void
+GeofenceAdapter::geofenceStatusEvent(GeofenceStatusAvailable available)
+{
+ LOC_LOGD("%s]: available %u ", __func__, available);
+
+ struct MsgGeofenceStatus : public LocMsg {
+ GeofenceAdapter& mAdapter;
+ GeofenceStatusAvailable mAvailable;
+ inline MsgGeofenceStatus(GeofenceAdapter& adapter,
+ GeofenceStatusAvailable available) :
+ LocMsg(),
+ mAdapter(adapter),
+ mAvailable(available) {}
+ inline virtual void proc() const {
+ mAdapter.geofenceStatus(mAvailable);
+ }
+ };
+
+ sendMsg(new MsgGeofenceStatus(*this, available));
+}
+
+void
+GeofenceAdapter::geofenceStatus(GeofenceStatusAvailable available)
+{
+ for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
+ if (it->second.geofenceStatusCb != nullptr) {
+ GeofenceStatusNotification notify = {sizeof(GeofenceStatusNotification),
+ available,
+ LOCATION_TECHNOLOGY_TYPE_GNSS};
+ it->second.geofenceStatusCb(notify);
+ }
+ }
+}
+
+void
+GeofenceAdapter::dump()
+{
+ IF_LOC_LOGV {
+ LOC_LOGV(
+ "HAL | hwId | mask | respon | latitude | longitude | radius | paused | Id | client");
+ for (auto it = mGeofences.begin(); it != mGeofences.end(); ++it) {
+ uint32_t hwId = it->first;
+ GeofenceObject object = it->second;
+ LOC_LOGV(" | %5u | %4u | %6u | %8.2f | %9.2f | %6.2f | %6u | %04x | %p ",
+ hwId, object.breachMask, object.responsiveness,
+ object.latitude, object.longitude, object.radius,
+ object.paused, object.key.id, object.key.client);
+ }
+ }
+}
+
diff --git a/gps/geofence/GeofenceAdapter.h b/gps/geofence/GeofenceAdapter.h
new file mode 100644
index 0000000..38f4823
--- /dev/null
+++ b/gps/geofence/GeofenceAdapter.h
@@ -0,0 +1,136 @@
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef GEOFENCE_ADAPTER_H
+#define GEOFENCE_ADAPTER_H
+
+#include <LocAdapterBase.h>
+#include <LocContext.h>
+#include <LocationAPI.h>
+#include <map>
+
+using namespace loc_core;
+
+#define COPY_IF_NOT_NULL(dest, src, len) do { \
+ if (NULL!=dest && NULL!=src) { \
+ for (size_t i=0; i<len; ++i) { \
+ dest[i] = src[i]; \
+ } \
+ } \
+} while (0)
+
+typedef struct GeofenceKey {
+ LocationAPI* client;
+ uint32_t id;
+ inline GeofenceKey() :
+ client(NULL), id(0) {}
+ inline GeofenceKey(LocationAPI* _client, uint32_t _id) :
+ client(_client), id(_id) {}
+} GeofenceKey;
+inline bool operator <(GeofenceKey const& left, GeofenceKey const& right) {
+ return left.id < right.id || (left.id == right.id && left.client < right.client);
+}
+inline bool operator ==(GeofenceKey const& left, GeofenceKey const& right) {
+ return left.id == right.id && left.client == right.client;
+}
+inline bool operator !=(GeofenceKey const& left, GeofenceKey const& right) {
+ return left.id != right.id || left.client != right.client;
+}
+typedef struct {
+ GeofenceKey key;
+ GeofenceBreachTypeMask breachMask;
+ uint32_t responsiveness;
+ uint32_t dwellTime;
+ double latitude;
+ double longitude;
+ double radius;
+ bool paused;
+} GeofenceObject;
+typedef std::map<uint32_t, GeofenceObject> GeofencesMap; //map of hwId to GeofenceObject
+typedef std::map<GeofenceKey, uint32_t> GeofenceIdMap; //map of GeofenceKey to hwId
+
+class GeofenceAdapter : public LocAdapterBase {
+
+ /* ==== GEOFENCES ====================================================================== */
+ GeofencesMap mGeofences; //map hwId to GeofenceObject
+ GeofenceIdMap mGeofenceIds; //map of GeofenceKey to hwId
+
+protected:
+
+ /* ==== CLIENT ========================================================================= */
+ virtual void updateClientsEventMask();
+ virtual void stopClientSessions(LocationAPI* client);
+
+public:
+
+ GeofenceAdapter();
+ virtual ~GeofenceAdapter() {}
+
+ /* ==== SSR ============================================================================ */
+ /* ======== EVENTS ====(Called from QMI Thread)========================================= */
+ virtual void handleEngineUpEvent();
+ /* ======== UTILITIES ================================================================== */
+ void restartGeofences();
+
+ /* ==== GEOFENCES ====================================================================== */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ uint32_t* addGeofencesCommand(LocationAPI* client, size_t count,
+ GeofenceOption* options, GeofenceInfo* info);
+ void removeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids);
+ void pauseGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids);
+ void resumeGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids);
+ void modifyGeofencesCommand(LocationAPI* client, size_t count, uint32_t* ids,
+ GeofenceOption* options);
+ /* ======== RESPONSES ================================================================== */
+ void reportResponse(LocationAPI* client, size_t count, LocationError* errs, uint32_t* ids);
+ /* ======== UTILITIES ================================================================== */
+ void saveGeofenceItem(LocationAPI* client,
+ uint32_t clientId,
+ uint32_t hwId,
+ const GeofenceOption& options,
+ const GeofenceInfo& info);
+ void removeGeofenceItem(uint32_t hwId);
+ void pauseGeofenceItem(uint32_t hwId);
+ void resumeGeofenceItem(uint32_t hwId);
+ void modifyGeofenceItem(uint32_t hwId, const GeofenceOption& options);
+ LocationError getHwIdFromClient(LocationAPI* client, uint32_t clientId, uint32_t& hwId);
+ LocationError getGeofenceKeyFromHwId(uint32_t hwId, GeofenceKey& key);
+ void dump();
+
+ /* ==== REPORTS ======================================================================== */
+ /* ======== EVENTS ====(Called from QMI Thread)========================================= */
+ void geofenceBreachEvent(size_t count, uint32_t* hwIds, Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp);
+ void geofenceStatusEvent(GeofenceStatusAvailable available);
+ /* ======== UTILITIES ================================================================== */
+ void geofenceBreach(size_t count, uint32_t* hwIds, const Location& location,
+ GeofenceBreachType breachType, uint64_t timestamp);
+ void geofenceStatus(GeofenceStatusAvailable available);
+};
+
+#endif /* GEOFENCE_ADAPTER_H */
diff --git a/gps/geofence/Makefile.am b/gps/geofence/Makefile.am
new file mode 100644
index 0000000..61883ff
--- /dev/null
+++ b/gps/geofence/Makefile.am
@@ -0,0 +1,50 @@
+AM_CFLAGS = -Wundef \
+ -Wno-trigraphs \
+ -g -O0 \
+ -fno-inline \
+ -fno-short-enums \
+ -fpic \
+ ${GPSUTILS_CFLAGS} \
+ ${LOCCORE_CFLAGS} \
+ $(LOCPLA_CFLAGS) \
+ -D__func__=__PRETTY_FUNCTION__ \
+ -std=c++1y
+
+AM_CPPFLAGS = $(AM_CFLAGS)
+
+ACLOCAL_AMFLAGS = -I m4
+
+requiredlibs = \
+ ${LOCCORE_LIBS} \
+ $(GPSUTILS_LIBS) \
+ -llog
+
+h_sources = \
+ GeofenceAdapter.h
+
+c_sources = \
+ GeofenceAdapter.cpp \
+ location_geofence.cpp
+
+libgeofencing_la_SOURCES = $(c_sources)
+if USE_GLIB
+libgeofencing_la_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ $(AM_CFLAGS)
+libgeofencing_la_CPPFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ $(AM_CFLAGS) $(AM_CPPFLAGS)
+libgeofencing_la_LDFLAGS = -lstdc++ -Wl,-z,defs @GLIB_LIBS@ $(requiredlibs) -shared -version-info 1:0:0
+libgeofencing_la_LIBDADD = $(requiredlibs) -lstdc++ @GLIB_LIBS@
+else
+libgeofencing_la_CFLAGS = $(AM_CFLAGS)
+libgeofencing_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+libgeofencing_la_LDFLAGS = -lstdc++ -Wl,-z,defs $(requiredlibs) -shared -version-info 1:0:0
+libgeofencing_la_LIBDADD = $(requiredlibs) -lstdc++
+endif
+
+library_include_HEADERS = $(h_sources)
+
+library_includedir = $(pkgincludedir)
+
+lib_LTLIBRARIES = libgeofencing.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = location-geofence.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/gps/geofence/configure.ac b/gps/geofence/configure.ac
new file mode 100644
index 0000000..74eae7a
--- /dev/null
+++ b/gps/geofence/configure.ac
@@ -0,0 +1,72 @@
+AC_PREREQ(2.61)
+AC_INIT([location-geofence], 1.0.0)
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Check for programs
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Check for libraries
+PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
+AC_SUBST([GPSUTILS_CFLAGS])
+AC_SUBST([GPSUTILS_LIBS])
+
+PKG_CHECK_MODULES([LOCCORE], [loc-core])
+AC_SUBST([LOCCORE_CFLAGS])
+AC_SUBST([LOCCORE_LIBS])
+
+AS_CASE([$host],
+ [arm*], [ARM=yes],
+ [ARM=no]
+)
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x$with_locpla_includes" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+AC_SUBST([CFLAGS])
+AC_SUBST([CPPFLAGS])
+AC_SUBST([LIBS])
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ location-geofence.pc
+ ])
+
+AC_OUTPUT
diff --git a/gps/geofence/location-geofence.pc.in b/gps/geofence/location-geofence.pc.in
new file mode 100644
index 0000000..6a0781f
--- /dev/null
+++ b/gps/geofence/location-geofence.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: location-geofence
+Description: QTI GPS Geofence
+Version: @VERSION
+Libs: -L${libdir} -lgeofencing
+Cflags: -I${includedir}/location-geofence
diff --git a/gps/geofence/location_geofence.cpp b/gps/geofence/location_geofence.cpp
new file mode 100644
index 0000000..66729f4
--- /dev/null
+++ b/gps/geofence/location_geofence.cpp
@@ -0,0 +1,145 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "GeofenceAdapter.h"
+#include "location_interface.h"
+
+static GeofenceAdapter* gGeofenceAdapter = NULL;
+
+static void initialize();
+static void deinitialize();
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks);
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+static void requestCapabilities(LocationAPI* client);
+
+static uint32_t* addGeofences(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*);
+static void removeGeofences(LocationAPI* client, size_t count, uint32_t* ids);
+static void modifyGeofences(LocationAPI* client, size_t count, uint32_t* ids,
+ GeofenceOption* options);
+static void pauseGeofences(LocationAPI* client, size_t count, uint32_t* ids);
+static void resumeGeofences(LocationAPI* client, size_t count, uint32_t* ids);
+
+static const GeofenceInterface gGeofenceInterface = {
+ sizeof(GeofenceInterface),
+ initialize,
+ deinitialize,
+ addClient,
+ removeClient,
+ requestCapabilities,
+ addGeofences,
+ removeGeofences,
+ modifyGeofences,
+ pauseGeofences,
+ resumeGeofences
+};
+
+#ifndef DEBUG_X86
+extern "C" const GeofenceInterface* getGeofenceInterface()
+#else
+const GeofenceInterface* getGeofenceInterface()
+#endif // DEBUG_X86
+{
+ return &gGeofenceInterface;
+}
+
+static void initialize()
+{
+ if (NULL == gGeofenceAdapter) {
+ gGeofenceAdapter = new GeofenceAdapter();
+ }
+}
+
+static void deinitialize()
+{
+ if (NULL != gGeofenceAdapter) {
+ delete gGeofenceAdapter;
+ gGeofenceAdapter = NULL;
+ }
+}
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ if (NULL != gGeofenceAdapter) {
+ gGeofenceAdapter->addClientCommand(client, callbacks);
+ }
+}
+
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb)
+{
+ if (NULL != gGeofenceAdapter) {
+ gGeofenceAdapter->removeClientCommand(client, rmClientCb);
+ }
+}
+
+static void requestCapabilities(LocationAPI* client)
+{
+ if (NULL != gGeofenceAdapter) {
+ gGeofenceAdapter->requestCapabilitiesCommand(client);
+ }
+}
+
+static uint32_t* addGeofences(LocationAPI* client, size_t count,
+ GeofenceOption* options, GeofenceInfo* info)
+{
+ if (NULL != gGeofenceAdapter) {
+ return gGeofenceAdapter->addGeofencesCommand(client, count, options, info);
+ } else {
+ return NULL;
+ }
+}
+
+static void removeGeofences(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ if (NULL != gGeofenceAdapter) {
+ return gGeofenceAdapter->removeGeofencesCommand(client, count, ids);
+ }
+}
+
+static void modifyGeofences(LocationAPI* client, size_t count, uint32_t* ids,
+ GeofenceOption* options)
+{
+ if (NULL != gGeofenceAdapter) {
+ return gGeofenceAdapter->modifyGeofencesCommand(client, count, ids, options);
+ }
+}
+
+static void pauseGeofences(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ if (NULL != gGeofenceAdapter) {
+ return gGeofenceAdapter->pauseGeofencesCommand(client, count, ids);
+ }
+}
+
+static void resumeGeofences(LocationAPI* client, size_t count, uint32_t* ids)
+{
+ if (NULL != gGeofenceAdapter) {
+ return gGeofenceAdapter->resumeGeofencesCommand(client, count, ids);
+ }
+}
+
diff --git a/gps/gnss/Agps.cpp b/gps/gnss/Agps.cpp
new file mode 100644
index 0000000..9255f88
--- /dev/null
+++ b/gps/gnss/Agps.cpp
@@ -0,0 +1,675 @@
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_Agps"
+
+#include <Agps.h>
+#include <loc_pla.h>
+#include <ContextBase.h>
+#include <loc_timer.h>
+#include <inttypes.h>
+
+/* --------------------------------------------------------------------
+ * AGPS State Machine Methods
+ * -------------------------------------------------------------------*/
+void AgpsStateMachine::processAgpsEvent(AgpsEvent event){
+
+ LOC_LOGD("processAgpsEvent(): SM %p, Event %d, State %d",
+ this, event, mState);
+
+ switch (event) {
+
+ case AGPS_EVENT_SUBSCRIBE:
+ processAgpsEventSubscribe();
+ break;
+
+ case AGPS_EVENT_UNSUBSCRIBE:
+ processAgpsEventUnsubscribe();
+ break;
+
+ case AGPS_EVENT_GRANTED:
+ processAgpsEventGranted();
+ break;
+
+ case AGPS_EVENT_RELEASED:
+ processAgpsEventReleased();
+ break;
+
+ case AGPS_EVENT_DENIED:
+ processAgpsEventDenied();
+ break;
+
+ default:
+ LOC_LOGE("Invalid Loc Agps Event");
+ }
+}
+
+void AgpsStateMachine::processAgpsEventSubscribe(){
+
+ switch (mState) {
+
+ case AGPS_STATE_RELEASED:
+ /* Add subscriber to list
+ * No notifications until we get RSRC_GRANTED */
+ addSubscriber(mCurrentSubscriber);
+ requestOrReleaseDataConn(true);
+ transitionState(AGPS_STATE_PENDING);
+ break;
+
+ case AGPS_STATE_PENDING:
+ /* Already requested for data connection,
+ * do nothing until we get RSRC_GRANTED event;
+ * Just add this subscriber to the list, for notifications */
+ addSubscriber(mCurrentSubscriber);
+ break;
+
+ case AGPS_STATE_ACQUIRED:
+ /* We already have the data connection setup,
+ * Notify current subscriber with GRANTED event,
+ * And add it to the subscriber list for further notifications. */
+ notifyEventToSubscriber(AGPS_EVENT_GRANTED, mCurrentSubscriber, false);
+ addSubscriber(mCurrentSubscriber);
+ break;
+
+ case AGPS_STATE_RELEASING:
+ addSubscriber(mCurrentSubscriber);
+ break;
+
+ default:
+ LOC_LOGE("Invalid state: %d", mState);
+ }
+}
+
+void AgpsStateMachine::processAgpsEventUnsubscribe(){
+
+ switch (mState) {
+
+ case AGPS_STATE_RELEASED:
+ notifyEventToSubscriber(
+ AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
+ break;
+
+ case AGPS_STATE_PENDING:
+ case AGPS_STATE_ACQUIRED:
+ /* If the subscriber wishes to wait for connection close,
+ * before being removed from list, move to inactive state
+ * and notify */
+ if (mCurrentSubscriber->mWaitForCloseComplete) {
+ mCurrentSubscriber->mIsInactive = true;
+ }
+ else {
+ /* Notify only current subscriber and then delete it from
+ * subscriberList */
+ notifyEventToSubscriber(
+ AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
+ }
+
+ /* If no subscribers in list, release data connection */
+ if (mSubscriberList.empty()) {
+ transitionState(AGPS_STATE_RELEASED);
+ requestOrReleaseDataConn(false);
+ }
+ /* Some subscribers in list, but all inactive;
+ * Release data connection */
+ else if(!anyActiveSubscribers()) {
+ transitionState(AGPS_STATE_RELEASING);
+ requestOrReleaseDataConn(false);
+ }
+ break;
+
+ case AGPS_STATE_RELEASING:
+ /* If the subscriber wishes to wait for connection close,
+ * before being removed from list, move to inactive state
+ * and notify */
+ if (mCurrentSubscriber->mWaitForCloseComplete) {
+ mCurrentSubscriber->mIsInactive = true;
+ }
+ else {
+ /* Notify only current subscriber and then delete it from
+ * subscriberList */
+ notifyEventToSubscriber(
+ AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
+ }
+
+ /* If no subscribers in list, just move the state.
+ * Request for releasing data connection should already have been
+ * sent */
+ if (mSubscriberList.empty()) {
+ transitionState(AGPS_STATE_RELEASED);
+ }
+ break;
+
+ default:
+ LOC_LOGE("Invalid state: %d", mState);
+ }
+}
+
+void AgpsStateMachine::processAgpsEventGranted(){
+
+ switch (mState) {
+
+ case AGPS_STATE_RELEASED:
+ case AGPS_STATE_ACQUIRED:
+ case AGPS_STATE_RELEASING:
+ LOC_LOGE("Unexpected event GRANTED in state %d", mState);
+ break;
+
+ case AGPS_STATE_PENDING:
+ // Move to acquired state
+ transitionState(AGPS_STATE_ACQUIRED);
+ notifyAllSubscribers(
+ AGPS_EVENT_GRANTED, false,
+ AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS);
+ break;
+
+ default:
+ LOC_LOGE("Invalid state: %d", mState);
+ }
+}
+
+void AgpsStateMachine::processAgpsEventReleased(){
+
+ switch (mState) {
+
+ case AGPS_STATE_RELEASED:
+ /* Subscriber list should be empty if we are in released state */
+ if (!mSubscriberList.empty()) {
+ LOC_LOGE("Unexpected event RELEASED in RELEASED state");
+ }
+ break;
+
+ case AGPS_STATE_ACQUIRED:
+ /* Force release received */
+ LOC_LOGW("Force RELEASED event in ACQUIRED state");
+ transitionState(AGPS_STATE_RELEASED);
+ notifyAllSubscribers(
+ AGPS_EVENT_RELEASED, true,
+ AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
+ break;
+
+ case AGPS_STATE_RELEASING:
+ /* Notify all inactive subscribers about the event */
+ notifyAllSubscribers(
+ AGPS_EVENT_RELEASED, true,
+ AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
+
+ /* If we have active subscribers now, they must be waiting for
+ * data conn setup */
+ if (anyActiveSubscribers()) {
+ transitionState(AGPS_STATE_PENDING);
+ requestOrReleaseDataConn(true);
+ }
+ /* No active subscribers, move to released state */
+ else {
+ transitionState(AGPS_STATE_RELEASED);
+ }
+ break;
+
+ case AGPS_STATE_PENDING:
+ /* NOOP */
+ break;
+
+ default:
+ LOC_LOGE("Invalid state: %d", mState);
+ }
+}
+
+void AgpsStateMachine::processAgpsEventDenied(){
+
+ switch (mState) {
+
+ case AGPS_STATE_RELEASED:
+ LOC_LOGE("Unexpected event DENIED in state %d", mState);
+ break;
+
+ case AGPS_STATE_ACQUIRED:
+ /* NOOP */
+ break;
+
+ case AGPS_STATE_RELEASING:
+ /* Notify all inactive subscribers about the event */
+ notifyAllSubscribers(
+ AGPS_EVENT_RELEASED, true,
+ AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
+
+ /* If we have active subscribers now, they must be waiting for
+ * data conn setup */
+ if (anyActiveSubscribers()) {
+ transitionState(AGPS_STATE_PENDING);
+ requestOrReleaseDataConn(true);
+ }
+ /* No active subscribers, move to released state */
+ else {
+ transitionState(AGPS_STATE_RELEASED);
+ }
+ break;
+
+ case AGPS_STATE_PENDING:
+ transitionState(AGPS_STATE_RELEASED);
+ notifyAllSubscribers(
+ AGPS_EVENT_DENIED, true,
+ AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
+ break;
+
+ default:
+ LOC_LOGE("Invalid state: %d", mState);
+ }
+}
+
+/* Request or Release data connection
+ * bool request :
+ * true = Request data connection
+ * false = Release data connection */
+void AgpsStateMachine::requestOrReleaseDataConn(bool request){
+
+ AGnssExtStatusIpV4 nifRequest;
+ memset(&nifRequest, 0, sizeof(nifRequest));
+
+ nifRequest.type = mAgpsType;
+ nifRequest.apnTypeMask = mApnTypeMask;
+ if (request) {
+ LOC_LOGD("AGPS Data Conn Request mAgpsType=%d mApnTypeMask=0x%X",
+ mAgpsType, mApnTypeMask);
+ nifRequest.status = LOC_GPS_REQUEST_AGPS_DATA_CONN;
+ }
+ else{
+ LOC_LOGD("AGPS Data Conn Release mAgpsType=%d mApnTypeMask=0x%X",
+ mAgpsType, mApnTypeMask);
+ nifRequest.status = LOC_GPS_RELEASE_AGPS_DATA_CONN;
+ }
+
+ mFrameworkStatusV4Cb(nifRequest);
+}
+
+void AgpsStateMachine::notifyAllSubscribers(
+ AgpsEvent event, bool deleteSubscriberPostNotify,
+ AgpsNotificationType notificationType){
+
+ LOC_LOGD("notifyAllSubscribers(): "
+ "SM %p, Event %d Delete %d Notification Type %d",
+ this, event, deleteSubscriberPostNotify, notificationType);
+
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ while ( it != mSubscriberList.end() ) {
+
+ AgpsSubscriber* subscriber = *it;
+
+ if (notificationType == AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS ||
+ (notificationType == AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS &&
+ subscriber->mIsInactive) ||
+ (notificationType == AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS &&
+ !subscriber->mIsInactive)) {
+
+ /* Deleting via this call would require another traversal
+ * through subscriber list, inefficient; hence pass in false*/
+ notifyEventToSubscriber(event, subscriber, false);
+
+ if (deleteSubscriberPostNotify) {
+ it = mSubscriberList.erase(it);
+ delete subscriber;
+ } else {
+ it++;
+ }
+ } else {
+ it++;
+ }
+ }
+}
+
+void AgpsStateMachine::notifyEventToSubscriber(
+ AgpsEvent event, AgpsSubscriber* subscriberToNotify,
+ bool deleteSubscriberPostNotify) {
+
+ LOC_LOGD("notifyEventToSubscriber(): "
+ "SM %p, Event %d Subscriber %p Delete %d",
+ this, event, subscriberToNotify, deleteSubscriberPostNotify);
+
+ switch (event) {
+
+ case AGPS_EVENT_GRANTED:
+ mAgpsManager->mAtlOpenStatusCb(
+ subscriberToNotify->mConnHandle, 1, getAPN(), getAPNLen(),
+ getBearer(), mAgpsType, mApnTypeMask);
+ break;
+
+ case AGPS_EVENT_DENIED:
+ mAgpsManager->mAtlOpenStatusCb(
+ subscriberToNotify->mConnHandle, 0, getAPN(), getAPNLen(),
+ getBearer(), mAgpsType, mApnTypeMask);
+ break;
+
+ case AGPS_EVENT_UNSUBSCRIBE:
+ case AGPS_EVENT_RELEASED:
+ mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
+ break;
+
+ default:
+ LOC_LOGE("Invalid event %d", event);
+ }
+
+ /* Search this subscriber in list and delete */
+ if (deleteSubscriberPostNotify) {
+ deleteSubscriber(subscriberToNotify);
+ }
+}
+
+void AgpsStateMachine::transitionState(AgpsState newState){
+
+ LOC_LOGD("transitionState(): SM %p, old %d, new %d",
+ this, mState, newState);
+
+ mState = newState;
+
+ // notify state transitions to all subscribers ?
+}
+
+void AgpsStateMachine::addSubscriber(AgpsSubscriber* subscriberToAdd){
+
+ LOC_LOGD("addSubscriber(): SM %p, Subscriber %p",
+ this, subscriberToAdd);
+
+ // Check if subscriber is already present in the current list
+ // If not, then add
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ for (; it != mSubscriberList.end(); it++) {
+ AgpsSubscriber* subscriber = *it;
+ if (subscriber->equals(subscriberToAdd)) {
+ LOC_LOGE("Subscriber already in list");
+ return;
+ }
+ }
+
+ AgpsSubscriber* cloned = subscriberToAdd->clone();
+ LOC_LOGD("addSubscriber(): cloned subscriber: %p", cloned);
+ mSubscriberList.push_back(cloned);
+}
+
+void AgpsStateMachine::deleteSubscriber(AgpsSubscriber* subscriberToDelete){
+
+ LOC_LOGD("deleteSubscriber(): SM %p, Subscriber %p",
+ this, subscriberToDelete);
+
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ while ( it != mSubscriberList.end() ) {
+
+ AgpsSubscriber* subscriber = *it;
+ if (subscriber && subscriber->equals(subscriberToDelete)) {
+
+ it = mSubscriberList.erase(it);
+ delete subscriber;
+ } else {
+ it++;
+ }
+ }
+}
+
+bool AgpsStateMachine::anyActiveSubscribers(){
+
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ for (; it != mSubscriberList.end(); it++) {
+ AgpsSubscriber* subscriber = *it;
+ if (!subscriber->mIsInactive) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void AgpsStateMachine::setAPN(char* apn, unsigned int len){
+
+ if (NULL != mAPN) {
+ delete mAPN;
+ mAPN = NULL;
+ }
+
+ if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) {
+ LOC_LOGD("Invalid apn len (%d) or null apn", len);
+ mAPN = NULL;
+ mAPNLen = 0;
+ } else {
+ mAPN = new char[len+1];
+ if (NULL != mAPN) {
+ memcpy(mAPN, apn, len);
+ mAPN[len] = '\0';
+ mAPNLen = len;
+ }
+ }
+}
+
+AgpsSubscriber* AgpsStateMachine::getSubscriber(int connHandle){
+
+ /* Go over the subscriber list */
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ for (; it != mSubscriberList.end(); it++) {
+ AgpsSubscriber* subscriber = *it;
+ if (subscriber->mConnHandle == connHandle) {
+ return subscriber;
+ }
+ }
+
+ /* Not found, return NULL */
+ return NULL;
+}
+
+AgpsSubscriber* AgpsStateMachine::getFirstSubscriber(bool isInactive){
+
+ /* Go over the subscriber list */
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ for (; it != mSubscriberList.end(); it++) {
+ AgpsSubscriber* subscriber = *it;
+ if(subscriber->mIsInactive == isInactive) {
+ return subscriber;
+ }
+ }
+
+ /* Not found, return NULL */
+ return NULL;
+}
+
+void AgpsStateMachine::dropAllSubscribers(){
+
+ LOC_LOGD("dropAllSubscribers(): SM %p", this);
+
+ /* Go over the subscriber list */
+ std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
+ while ( it != mSubscriberList.end() ) {
+ AgpsSubscriber* subscriber = *it;
+ it = mSubscriberList.erase(it);
+ delete subscriber;
+ }
+}
+
+/* --------------------------------------------------------------------
+ * Loc AGPS Manager Methods
+ * -------------------------------------------------------------------*/
+
+/* CREATE AGPS STATE MACHINES
+ * Must be invoked in Msg Handler context */
+void AgpsManager::createAgpsStateMachines(const AgpsCbInfo& cbInfo) {
+
+ LOC_LOGD("AgpsManager::createAgpsStateMachines");
+
+ bool agpsCapable =
+ ((loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA) ||
+ (loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB));
+
+ if (NULL == mInternetNif && (cbInfo.atlType & AGPS_ATL_TYPE_WWAN)) {
+ mInternetNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_WWAN_ANY);
+ mInternetNif->registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb);
+ LOC_LOGD("Internet NIF: %p", mInternetNif);
+ }
+ if (agpsCapable) {
+ if (NULL == mAgnssNif && (cbInfo.atlType & AGPS_ATL_TYPE_SUPL) &&
+ (cbInfo.atlType & AGPS_ATL_TYPE_SUPL_ES)) {
+ mAgnssNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_SUPL);
+ mAgnssNif->registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb);
+ LOC_LOGD("AGNSS NIF: %p", mAgnssNif);
+ }
+ }
+}
+
+AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType agpsType) {
+
+ LOC_LOGD("AgpsManager::getAgpsStateMachine(): agpsType %d", agpsType);
+
+ switch (agpsType) {
+
+ case LOC_AGPS_TYPE_INVALID:
+ case LOC_AGPS_TYPE_SUPL:
+ case LOC_AGPS_TYPE_SUPL_ES:
+ if (mAgnssNif == NULL) {
+ LOC_LOGE("NULL AGNSS NIF !");
+ }
+ return mAgnssNif;
+ case LOC_AGPS_TYPE_WWAN_ANY:
+ if (mInternetNif == NULL) {
+ LOC_LOGE("NULL Internet NIF !");
+ }
+ return mInternetNif;
+ default:
+ return mInternetNif;
+ }
+
+ LOC_LOGE("No SM found !");
+ return NULL;
+}
+
+void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType,
+ LocApnTypeMask apnTypeMask){
+
+ LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType 0x%X apnTypeMask: 0x%X",
+ connHandle, agpsType, apnTypeMask);
+
+ if (0 == loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL &&
+ LOC_AGPS_TYPE_SUPL_ES == agpsType) {
+ agpsType = LOC_AGPS_TYPE_SUPL;
+ apnTypeMask &= ~LOC_APN_TYPE_MASK_EMERGENCY;
+ apnTypeMask |= LOC_APN_TYPE_MASK_SUPL;
+ LOC_LOGD("Changed agpsType to non-emergency when USE_EMERGENCY... is 0"
+ "and removed LOC_APN_TYPE_MASK_EMERGENCY from apnTypeMask"
+ "agpsType 0x%X apnTypeMask : 0x%X",
+ agpsType, apnTypeMask);
+ }
+ AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
+
+ if (sm == NULL) {
+
+ LOC_LOGE("No AGPS State Machine for agpsType: %d apnTypeMask: 0x%X",
+ agpsType, apnTypeMask);
+ mAtlOpenStatusCb(
+ connHandle, 0, NULL, 0, AGPS_APN_BEARER_INVALID, agpsType, apnTypeMask);
+ return;
+ }
+ sm->setType(agpsType);
+ sm->setApnTypeMask(apnTypeMask);
+
+ /* Invoke AGPS SM processing */
+ AgpsSubscriber subscriber(connHandle, false, false, apnTypeMask);
+ sm->setCurrentSubscriber(&subscriber);
+ /* Send subscriber event */
+ sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE);
+}
+
+void AgpsManager::releaseATL(int connHandle){
+
+ LOC_LOGD("AgpsManager::releaseATL(): connHandle %d", connHandle);
+
+ /* First find the subscriber with specified handle.
+ * We need to search in all state machines. */
+ AgpsStateMachine* sm = NULL;
+ AgpsSubscriber* subscriber = NULL;
+
+ if (mAgnssNif &&
+ (subscriber = mAgnssNif->getSubscriber(connHandle)) != NULL) {
+ sm = mAgnssNif;
+ }
+ else if (mInternetNif &&
+ (subscriber = mInternetNif->getSubscriber(connHandle)) != NULL) {
+ sm = mInternetNif;
+ }
+ if (sm == NULL) {
+ LOC_LOGE("Subscriber with connHandle %d not found in any SM",
+ connHandle);
+ return;
+ }
+
+ /* Now send unsubscribe event */
+ sm->setCurrentSubscriber(subscriber);
+ sm->processAgpsEvent(AGPS_EVENT_UNSUBSCRIBE);
+}
+
+void AgpsManager::reportAtlOpenSuccess(
+ AGpsExtType agpsType, char* apnName, int apnLen,
+ AGpsBearerType bearerType){
+
+ LOC_LOGD("AgpsManager::reportAtlOpenSuccess(): "
+ "AgpsType %d, APN [%s], Len %d, BearerType %d",
+ agpsType, apnName, apnLen, bearerType);
+
+ /* Find the state machine instance */
+ AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
+
+ /* Set bearer and apn info in state machine instance */
+ sm->setBearer(bearerType);
+ sm->setAPN(apnName, apnLen);
+
+ /* Send GRANTED event to state machine */
+ sm->processAgpsEvent(AGPS_EVENT_GRANTED);
+}
+
+void AgpsManager::reportAtlOpenFailed(AGpsExtType agpsType){
+
+ LOC_LOGD("AgpsManager::reportAtlOpenFailed(): AgpsType %d", agpsType);
+
+ /* Fetch SM and send DENIED event */
+ AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
+ sm->processAgpsEvent(AGPS_EVENT_DENIED);
+}
+
+void AgpsManager::reportAtlClosed(AGpsExtType agpsType){
+
+ LOC_LOGD("AgpsManager::reportAtlClosed(): AgpsType %d", agpsType);
+
+ /* Fetch SM and send RELEASED event */
+ AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
+ sm->processAgpsEvent(AGPS_EVENT_RELEASED);
+}
+
+void AgpsManager::handleModemSSR(){
+
+ LOC_LOGD("AgpsManager::handleModemSSR");
+
+ /* Drop subscribers from all state machines */
+ if (mAgnssNif) {
+ mAgnssNif->dropAllSubscribers();
+ }
+ if (mInternetNif) {
+ mInternetNif->dropAllSubscribers();
+ }
+}
diff --git a/gps/gnss/Agps.h b/gps/gnss/Agps.h
new file mode 100644
index 0000000..6b43bf5
--- /dev/null
+++ b/gps/gnss/Agps.h
@@ -0,0 +1,318 @@
+/* Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef AGPS_H
+#define AGPS_H
+
+#include <functional>
+#include <list>
+#include <MsgTask.h>
+#include <gps_extended_c.h>
+#include <loc_pla.h>
+#include <log_util.h>
+
+using namespace loc_util;
+
+/* ATL callback function pointers
+ * Passed in by Adapter to AgpsManager */
+typedef std::function<void(
+ int handle, int isSuccess, char* apn, uint32_t apnLen,
+ AGpsBearerType bearerType, AGpsExtType agpsType,
+ LocApnTypeMask mask)> AgpsAtlOpenStatusCb;
+
+typedef std::function<void(int handle, int isSuccess)> AgpsAtlCloseStatusCb;
+
+/* Post message to adapter's message queue */
+typedef std::function<void(LocMsg* msg)> SendMsgToAdapterMsgQueueFn;
+
+/* AGPS States */
+typedef enum {
+ AGPS_STATE_INVALID = 0,
+ AGPS_STATE_RELEASED,
+ AGPS_STATE_PENDING,
+ AGPS_STATE_ACQUIRED,
+ AGPS_STATE_RELEASING
+} AgpsState;
+
+typedef enum {
+ AGPS_EVENT_INVALID = 0,
+ AGPS_EVENT_SUBSCRIBE,
+ AGPS_EVENT_UNSUBSCRIBE,
+ AGPS_EVENT_GRANTED,
+ AGPS_EVENT_RELEASED,
+ AGPS_EVENT_DENIED
+} AgpsEvent;
+
+/* Notification Types sent to subscribers */
+typedef enum {
+ AGPS_NOTIFICATION_TYPE_INVALID = 0,
+
+ /* Meant for all subscribers, either active or inactive */
+ AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS,
+
+ /* Meant for only inactive subscribers */
+ AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS,
+
+ /* Meant for only active subscribers */
+ AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS
+} AgpsNotificationType;
+
+/* Classes in this header */
+class AgpsSubscriber;
+class AgpsManager;
+class AgpsStateMachine;
+
+/* SUBSCRIBER
+ * Each Subscriber instance corresponds to one AGPS request,
+ * received by the AGPS state machine */
+class AgpsSubscriber {
+
+public:
+ int mConnHandle;
+
+ /* Does this subscriber wait for data call close complete,
+ * before being notified ATL close ?
+ * While waiting for data call close, subscriber will be in
+ * inactive state. */
+ bool mWaitForCloseComplete;
+ bool mIsInactive;
+ LocApnTypeMask mApnTypeMask;
+
+ inline AgpsSubscriber(
+ int connHandle, bool waitForCloseComplete, bool isInactive,
+ LocApnTypeMask apnTypeMask) :
+ mConnHandle(connHandle),
+ mWaitForCloseComplete(waitForCloseComplete),
+ mIsInactive(isInactive),
+ mApnTypeMask(apnTypeMask) {}
+ inline virtual ~AgpsSubscriber() {}
+
+ inline virtual bool equals(const AgpsSubscriber *s) const
+ { return (mConnHandle == s->mConnHandle); }
+
+ inline virtual AgpsSubscriber* clone()
+ { return new AgpsSubscriber(
+ mConnHandle, mWaitForCloseComplete, mIsInactive, mApnTypeMask); }
+};
+
+/* AGPS STATE MACHINE */
+class AgpsStateMachine {
+protected:
+ /* AGPS Manager instance, from where this state machine is created */
+ AgpsManager* mAgpsManager;
+
+ /* List of all subscribers for this State Machine.
+ * Once a subscriber is notified for ATL open/close status,
+ * it is deleted */
+ std::list<AgpsSubscriber*> mSubscriberList;
+
+ /* Current subscriber, whose request this State Machine is
+ * currently processing */
+ AgpsSubscriber* mCurrentSubscriber;
+
+ /* Current state for this state machine */
+ AgpsState mState;
+
+ AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
+private:
+ /* AGPS Type for this state machine
+ LOC_AGPS_TYPE_ANY 0
+ LOC_AGPS_TYPE_SUPL 1
+ LOC_AGPS_TYPE_WWAN_ANY 3
+ LOC_AGPS_TYPE_SUPL_ES 5 */
+ AGpsExtType mAgpsType;
+ LocApnTypeMask mApnTypeMask;
+
+ /* APN and IP Type info for AGPS Call */
+ char* mAPN;
+ unsigned int mAPNLen;
+ AGpsBearerType mBearer;
+
+public:
+ /* CONSTRUCTOR */
+ AgpsStateMachine(AgpsManager* agpsManager, AGpsExtType agpsType):
+ mFrameworkStatusV4Cb(NULL),
+ mAgpsManager(agpsManager), mSubscriberList(),
+ mCurrentSubscriber(NULL), mState(AGPS_STATE_RELEASED),
+ mAgpsType(agpsType), mAPN(NULL), mAPNLen(0),
+ mBearer(AGPS_APN_BEARER_INVALID) {};
+
+ virtual ~AgpsStateMachine() { if(NULL != mAPN) delete[] mAPN; };
+
+ /* Getter/Setter methods */
+ void setAPN(char* apn, unsigned int len);
+ inline char* getAPN() const { return (char*)mAPN; }
+ inline uint32_t getAPNLen() const { return mAPNLen; }
+ inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
+ inline LocApnTypeMask getApnTypeMask() const { return mApnTypeMask; }
+ inline void setApnTypeMask(LocApnTypeMask apnTypeMask)
+ { mApnTypeMask = apnTypeMask; }
+ inline AGpsBearerType getBearer() const { return mBearer; }
+ inline void setType(AGpsExtType type) { mAgpsType = type; }
+ inline AGpsExtType getType() const { return mAgpsType; }
+ inline void setCurrentSubscriber(AgpsSubscriber* subscriber)
+ { mCurrentSubscriber = subscriber; }
+
+ inline void registerFrameworkStatusCallback(AgnssStatusIpV4Cb frameworkStatusV4Cb) {
+ mFrameworkStatusV4Cb = frameworkStatusV4Cb;
+ }
+
+ /* Fetch subscriber with specified handle */
+ AgpsSubscriber* getSubscriber(int connHandle);
+
+ /* Fetch first active or inactive subscriber in list
+ * isInactive = true : fetch first inactive subscriber
+ * isInactive = false : fetch first active subscriber */
+ AgpsSubscriber* getFirstSubscriber(bool isInactive);
+
+ /* Process LOC AGPS Event being passed in
+ * onRsrcEvent */
+ virtual void processAgpsEvent(AgpsEvent event);
+
+ /* Drop all subscribers, in case of Modem SSR */
+ void dropAllSubscribers();
+
+protected:
+ /* Remove the specified subscriber from list if present.
+ * Also delete the subscriber instance. */
+ void deleteSubscriber(AgpsSubscriber* subscriber);
+
+private:
+ /* Send call setup request to framework
+ * sendRsrcRequest(LOC_GPS_REQUEST_AGPS_DATA_CONN)
+ * sendRsrcRequest(LOC_GPS_RELEASE_AGPS_DATA_CONN) */
+ void requestOrReleaseDataConn(bool request);
+
+ /* Individual event processing methods */
+ void processAgpsEventSubscribe();
+ void processAgpsEventUnsubscribe();
+ void processAgpsEventGranted();
+ void processAgpsEventReleased();
+ void processAgpsEventDenied();
+
+ /* Clone the passed in subscriber and add to the subscriber list
+ * if not already present */
+ void addSubscriber(AgpsSubscriber* subscriber);
+
+ /* Notify subscribers about AGPS events */
+ void notifyAllSubscribers(
+ AgpsEvent event, bool deleteSubscriberPostNotify,
+ AgpsNotificationType notificationType);
+ virtual void notifyEventToSubscriber(
+ AgpsEvent event, AgpsSubscriber* subscriber,
+ bool deleteSubscriberPostNotify);
+
+ /* Do we have any subscribers in active state */
+ bool anyActiveSubscribers();
+
+ /* Transition state */
+ void transitionState(AgpsState newState);
+};
+
+/* LOC AGPS MANAGER */
+class AgpsManager {
+
+ friend class AgpsStateMachine;
+public:
+ /* CONSTRUCTOR */
+ AgpsManager():
+ mAtlOpenStatusCb(), mAtlCloseStatusCb(),
+ mAgnssNif(NULL), mInternetNif(NULL)/*, mDsNif(NULL)*/ {}
+
+ /* Register callbacks */
+ inline void registerATLCallbacks(AgpsAtlOpenStatusCb atlOpenStatusCb,
+ AgpsAtlCloseStatusCb atlCloseStatusCb) {
+
+ mAtlOpenStatusCb = atlOpenStatusCb;
+ mAtlCloseStatusCb = atlCloseStatusCb;
+ }
+
+ /* Check if AGPS client is registered */
+ inline bool isRegistered() { return nullptr != mAgnssNif || nullptr != mInternetNif; }
+
+ /* Create all AGPS state machines */
+ void createAgpsStateMachines(const AgpsCbInfo& cbInfo);
+
+ /* Process incoming ATL requests */
+ void requestATL(int connHandle, AGpsExtType agpsType, LocApnTypeMask apnTypeMask);
+ void releaseATL(int connHandle);
+ /* Process incoming framework data call events */
+ void reportAtlOpenSuccess(AGpsExtType agpsType, char* apnName, int apnLen,
+ AGpsBearerType bearerType);
+ void reportAtlOpenFailed(AGpsExtType agpsType);
+ void reportAtlClosed(AGpsExtType agpsType);
+
+ /* Handle Modem SSR */
+ void handleModemSSR();
+
+protected:
+
+ AgpsAtlOpenStatusCb mAtlOpenStatusCb;
+ AgpsAtlCloseStatusCb mAtlCloseStatusCb;
+ AgpsStateMachine* mAgnssNif;
+ AgpsStateMachine* mInternetNif;
+private:
+ /* Fetch state machine for handling request ATL call */
+ AgpsStateMachine* getAgpsStateMachine(AGpsExtType agpsType);
+};
+
+/* Request SUPL/INTERNET/SUPL_ES ATL
+ * This LocMsg is defined in this header since it has to be used from more
+ * than one place, other Agps LocMsg are restricted to GnssAdapter and
+ * declared inline */
+struct AgpsMsgRequestATL: public LocMsg {
+
+ AgpsManager* mAgpsManager;
+ int mConnHandle;
+ AGpsExtType mAgpsType;
+ LocApnTypeMask mApnTypeMask;
+
+ inline AgpsMsgRequestATL(AgpsManager* agpsManager, int connHandle,
+ AGpsExtType agpsType, LocApnTypeMask apnTypeMask) :
+ LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle),
+ mAgpsType(agpsType), mApnTypeMask(apnTypeMask){
+
+ LOC_LOGV("AgpsMsgRequestATL");
+ }
+
+ inline virtual void proc() const {
+
+ LOC_LOGV("AgpsMsgRequestATL::proc()");
+ mAgpsManager->requestATL(mConnHandle, mAgpsType, mApnTypeMask);
+ }
+};
+
+namespace AgpsUtils {
+
+AGpsBearerType ipTypeToBearerType(LocApnIpType ipType);
+LocApnIpType bearerTypeToIpType(AGpsBearerType bearerType);
+
+}
+
+#endif /* AGPS_H */
diff --git a/gps/gnss/Android.bp b/gps/gnss/Android.bp
new file mode 100644
index 0000000..a3e8de9
--- /dev/null
+++ b/gps/gnss/Android.bp
@@ -0,0 +1,35 @@
+
+
+cc_library_shared {
+
+ name: "libgnss",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ shared_libs: [
+ "libutils",
+ "libcutils",
+ "libdl",
+ "liblog",
+ "libloc_core",
+ "libgps.utils",
+ ],
+
+ srcs: [
+ "location_gnss.cpp",
+ "GnssAdapter.cpp",
+ "Agps.cpp",
+ "XtraSystemStatusObserver.cpp",
+ "NativeAgpsHandler.cpp",
+ ],
+
+ cflags: ["-fno-short-enums"] + GNSS_CFLAGS,
+ header_libs: [
+ "libgps.utils_headers",
+ "libloc_core_headers",
+ "libloc_pla_headers",
+ "liblocation_api_headers",
+ ],
+
+}
diff --git a/gps/gnss/GnssAdapter.cpp b/gps/gnss/GnssAdapter.cpp
new file mode 100644
index 0000000..cff0298
--- /dev/null
+++ b/gps/gnss/GnssAdapter.cpp
@@ -0,0 +1,6916 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_GnssAdapter"
+
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <math.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <GnssAdapter.h>
+#include <string>
+#include <sstream>
+#include <loc_log.h>
+#include <loc_nmea.h>
+#include <Agps.h>
+#include <SystemStatus.h>
+#include <vector>
+#include <loc_misc_utils.h>
+#include <gps_extended_c.h>
+
+#define RAD2DEG (180.0 / M_PI)
+#define DEG2RAD (M_PI / 180.0)
+#define PROCESS_NAME_ENGINE_SERVICE "engine-service"
+#define MIN_TRACKING_INTERVAL (100) // 100 msec
+
+#define BILLION_NSEC (1000000000ULL)
+#define NMEA_MIN_THRESHOLD_MSEC (99)
+#define NMEA_MAX_THRESHOLD_MSEC (975)
+
+#define DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI 600000
+
+using namespace loc_core;
+
+static int loadEngHubForExternalEngine = 0;
+static loc_param_s_type izatConfParamTable[] = {
+ {"LOAD_ENGHUB_FOR_EXTERNAL_ENGINE", &loadEngHubForExternalEngine, nullptr,'n'}
+};
+
+/* Method to fetch status cb from loc_net_iface library */
+typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
+ LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
+
+static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
+ AGpsBearerType bearerType, void* userDataPtr);
+static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
+
+typedef const CdfwInterface* (*getCdfwInterface)();
+
+inline bool GnssReportLoggerUtil::isLogEnabled() {
+ return (mLogLatency != nullptr);
+}
+
+inline void GnssReportLoggerUtil::log(const GnssLatencyInfo& gnssLatencyMeasInfo) {
+ if (mLogLatency != nullptr) {
+ mLogLatency(gnssLatencyMeasInfo);
+ }
+}
+
+GnssAdapter::GnssAdapter() :
+ LocAdapterBase(0,
+ LocContext::getLocContext(LocContext::mLocationHalName),
+ true, nullptr, true),
+ mEngHubProxy(new EngineHubProxyBase()),
+ mQDgnssListenerHDL(nullptr),
+ mCdfwInterface(nullptr),
+ mDGnssNeedReport(false),
+ mDGnssDataUsage(false),
+ mLocPositionMode(),
+ mNHzNeeded(false),
+ mSPEAlreadyRunningAtHighestInterval(false),
+ mGnssSvIdUsedInPosition(),
+ mGnssSvIdUsedInPosAvail(false),
+ mControlCallbacks(),
+ mAfwControlId(0),
+ mNmeaMask(0),
+ mGnssSvIdConfig(),
+ mGnssSeconaryBandConfig(),
+ mGnssSvTypeConfig(),
+ mGnssSvTypeConfigCb(nullptr),
+ mLocConfigInfo{},
+ mNiData(),
+ mAgpsManager(),
+ mOdcpiRequestCb(nullptr),
+ mOdcpiRequestActive(false),
+ mOdcpiTimer(this),
+ mOdcpiRequest(),
+ mCallbackPriority(OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW),
+ mSystemStatus(SystemStatus::getInstance(mMsgTask)),
+ mServerUrl(":"),
+ mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
+ mBlockCPIInfo{},
+ mDreIntEnabled(false),
+ mLocSystemInfo{},
+ mNfwCb(NULL),
+ mPowerOn(false),
+ mAllowFlpNetworkFixes(0),
+ mGnssEnergyConsumedCb(nullptr),
+ mPowerStateCb(nullptr),
+ mIsE911Session(NULL),
+ mGnssMbSvIdUsedInPosition{},
+ mGnssMbSvIdUsedInPosAvail(false),
+ mSupportNfwControl(true),
+ mSystemPowerState(POWER_STATE_UNKNOWN),
+ mIsMeasCorrInterfaceOpen(false),
+ mIsAntennaInfoInterfaceOpened(false),
+ mLastDeleteAidingDataTime(0),
+ mDgnssState(0),
+ mSendNmeaConsent(false),
+ mDgnssLastNmeaBootTimeMilli(0),
+ mNativeAgpsHandler(mSystemStatus->getOsObserver(), *this)
+{
+ LOC_LOGD("%s]: Constructor %p", __func__, this);
+ mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
+
+ pthread_condattr_t condAttr;
+ pthread_condattr_init(&condAttr);
+ pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
+ pthread_cond_init(&mNiData.session.tCond, &condAttr);
+ pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
+ pthread_condattr_destroy(&condAttr);
+
+ /* Set ATL open/close callbacks */
+ AgpsAtlOpenStatusCb atlOpenStatusCb =
+ [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
+ AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
+
+ mLocApi->atlOpenStatus(
+ handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
+ };
+ AgpsAtlCloseStatusCb atlCloseStatusCb =
+ [this](int handle, int isSuccess) {
+
+ mLocApi->atlCloseStatus(handle, isSuccess);
+ };
+ mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
+
+ readConfigCommand();
+ initDefaultAgpsCommand();
+ initEngHubProxyCommand();
+
+ // at last step, let us inform adapater base that we are done
+ // with initialization, e.g.: ready to process handleEngineUpEvent
+ doneInit();
+}
+
+void
+GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
+{
+ struct MsgSetControlCallbacks : public LocMsg {
+ GnssAdapter& mAdapter;
+ const LocationControlCallbacks mControlCallbacks;
+ inline MsgSetControlCallbacks(GnssAdapter& adapter,
+ LocationControlCallbacks& controlCallbacks) :
+ LocMsg(),
+ mAdapter(adapter),
+ mControlCallbacks(controlCallbacks) {}
+ inline virtual void proc() const {
+ mAdapter.setControlCallbacks(mControlCallbacks);
+ }
+ };
+
+ sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
+}
+
+void
+GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
+{
+ switch (trackingOptions.mode) {
+ case GNSS_SUPL_MODE_MSB:
+ out.mode = LOC_POSITION_MODE_MS_BASED;
+ break;
+ case GNSS_SUPL_MODE_MSA:
+ out.mode = LOC_POSITION_MODE_MS_ASSISTED;
+ break;
+ default:
+ out.mode = LOC_POSITION_MODE_STANDALONE;
+ break;
+ }
+ out.share_position = true;
+ out.min_interval = trackingOptions.minInterval;
+ out.powerMode = trackingOptions.powerMode;
+ out.timeBetweenMeasurements = trackingOptions.tbm;
+}
+
+bool
+GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
+
+ // first check if NHz meas is needed at all, if not, just return false
+ // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
+ // always run the SPE only session at 100ms TBF.
+ // If SPE session is already set to highest interval, no need to start it again.
+
+ bool isSPERunningAtHighestInterval = false;
+
+ if (!mNHzNeeded) {
+ LOC_LOGd("No nHz session needed.");
+ } else if (mSPEAlreadyRunningAtHighestInterval) {
+ LOC_LOGd("SPE is already running at highest interval.");
+ isSPERunningAtHighestInterval = true;
+ } else if (out.minInterval > MIN_TRACKING_INTERVAL) {
+ out.minInterval = MIN_TRACKING_INTERVAL;
+ LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF.");
+ mSPEAlreadyRunningAtHighestInterval = true;
+ }
+
+ return isSPERunningAtHighestInterval;
+}
+
+
+void
+GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended)
+{
+ memset(&out, 0, sizeof(Location));
+ out.size = sizeof(Location);
+ if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_LAT_LONG_BIT;
+ out.latitude = ulpLocation.gpsLocation.latitude;
+ out.longitude = ulpLocation.gpsLocation.longitude;
+ }
+ if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_ALTITUDE_BIT;
+ out.altitude = ulpLocation.gpsLocation.altitude;
+ }
+ if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_SPEED_BIT;
+ out.speed = ulpLocation.gpsLocation.speed;
+ }
+ if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_BEARING_BIT;
+ out.bearing = ulpLocation.gpsLocation.bearing;
+ }
+ if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_ACCURACY_BIT;
+ out.accuracy = ulpLocation.gpsLocation.accuracy;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
+ out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
+ out.verticalAccuracy = locationExtended.vert_unc;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
+ out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
+ out.speedAccuracy = locationExtended.speed_unc;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
+ out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
+ out.bearingAccuracy = locationExtended.bearing_unc;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
+ out.flags |= LOCATION_HAS_CONFORMITY_INDEX_BIT;
+ out.conformityIndex = locationExtended.conformityIndex;
+ }
+ out.timestamp = ulpLocation.gpsLocation.timestamp;
+ if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
+ }
+ if (LOC_POS_TECH_MASK_CELLID & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
+ }
+ if (LOC_POS_TECH_MASK_WIFI & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
+ }
+ if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
+ }
+ if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT;
+ }
+ if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT;
+ }
+ if (LOC_POS_TECH_MASK_AFLT & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_AFLT_BIT;
+ }
+ if (LOC_POS_TECH_MASK_HYBRID & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_HYBRID_BIT;
+ }
+ if (LOC_POS_TECH_MASK_PPE & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_PPE_BIT;
+ }
+ if (LOC_POS_TECH_MASK_VEH & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_VEH_BIT;
+ }
+ if (LOC_POS_TECH_MASK_VIS & locationExtended.tech_mask) {
+ out.techMask |= LOCATION_TECHNOLOGY_VIS_BIT;
+ }
+ if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask) {
+ out.techMask |= LOCATION_TECHNOLOGY_DGNSS_BIT;
+ }
+
+ if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_SPOOF_MASK;
+ out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
+ }
+ if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
+ out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
+ out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
+ }
+}
+
+/* This is utility routine that computes number of SV used
+ in the fix from the svUsedIdsMask.
+ */
+#define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
+uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
+ int totalSvCntInThisConstellation)
+{
+ if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
+ LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
+ totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
+ return 0;
+ }
+
+ uint16_t numSvUsed = 0;
+ uint64_t mask = 0x1;
+ for (int i = 0; i < totalSvCntInThisConstellation; i++) {
+ if (svUsedIdsMask & mask) {
+ numSvUsed++;
+ }
+ mask <<= 1;
+ }
+
+ return numSvUsed;
+}
+
+void
+GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status)
+{
+ out.size = sizeof(GnssLocationInfoNotification);
+ if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
+ out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
+ out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
+ out.pdop = locationExtended.extDOP.PDOP;
+ out.hdop = locationExtended.extDOP.HDOP;
+ out.vdop = locationExtended.extDOP.VDOP;
+ out.gdop = locationExtended.extDOP.GDOP;
+ out.tdop = locationExtended.extDOP.TDOP;
+ } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
+ out.pdop = locationExtended.pdop;
+ out.hdop = locationExtended.hdop;
+ out.vdop = locationExtended.vdop;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
+ out.magneticDeviation = locationExtended.magneticDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
+ switch (locationExtended.horizontal_reliability) {
+ case LOC_RELIABILITY_VERY_LOW:
+ out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
+ break;
+ case LOC_RELIABILITY_LOW:
+ out.horReliability = LOCATION_RELIABILITY_LOW;
+ break;
+ case LOC_RELIABILITY_MEDIUM:
+ out.horReliability = LOCATION_RELIABILITY_MEDIUM;
+ break;
+ case LOC_RELIABILITY_HIGH:
+ out.horReliability = LOCATION_RELIABILITY_HIGH;
+ break;
+ default:
+ out.horReliability = LOCATION_RELIABILITY_NOT_SET;
+ break;
+ }
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
+ switch (locationExtended.vertical_reliability) {
+ case LOC_RELIABILITY_VERY_LOW:
+ out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
+ break;
+ case LOC_RELIABILITY_LOW:
+ out.verReliability = LOCATION_RELIABILITY_LOW;
+ break;
+ case LOC_RELIABILITY_MEDIUM:
+ out.verReliability = LOCATION_RELIABILITY_MEDIUM;
+ break;
+ case LOC_RELIABILITY_HIGH:
+ out.verReliability = LOCATION_RELIABILITY_HIGH;
+ break;
+ default:
+ out.verReliability = LOCATION_RELIABILITY_NOT_SET;
+ break;
+ }
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
+ out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
+ out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
+ out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
+ out.northStdDeviation = locationExtended.northStdDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
+ out.eastStdDeviation = locationExtended.eastStdDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
+ out.northVelocity = locationExtended.northVelocity;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
+ out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
+ out.eastVelocity = locationExtended.eastVelocity;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
+ out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
+ out.upVelocity = locationExtended.upVelocity;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
+ out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
+ out.svUsedInPosition.gpsSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
+ out.svUsedInPosition.gloSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
+ out.svUsedInPosition.galSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
+ out.svUsedInPosition.bdsSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
+ out.svUsedInPosition.qzssSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
+ out.svUsedInPosition.navicSvUsedIdsMask =
+ locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
+
+ out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
+ out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
+ GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
+ out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
+ GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
+ out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
+ QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
+ out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
+ BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
+ out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
+ GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
+ out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.navicSvUsedIdsMask,
+ NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
+
+ out.numOfMeasReceived = locationExtended.numOfMeasReceived;
+ for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
+ out.measUsageInfo[idx].gnssSignalType =
+ locationExtended.measUsageInfo[idx].gnssSignalType;
+ out.measUsageInfo[idx].gnssSvId =
+ locationExtended.measUsageInfo[idx].gnssSvId;
+ out.measUsageInfo[idx].gnssConstellation =
+ locationExtended.measUsageInfo[idx].gnssConstellation;
+ }
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
+ out.navSolutionMask = locationExtended.navSolutionMask;
+ }
+ if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
+ out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_PITCH_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
+ }
+
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameData.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT) {
+ out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT;
+ }
+
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_ROLL_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_YAW_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_BIT;
+ }
+ if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
+ LOCATION_NAV_DATA_HAS_YAW_UNC_BIT) {
+ out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_UNC_BIT;
+ }
+
+ out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
+ out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
+ out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
+ out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
+ out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
+ out.bodyFrameData.longAccelUnc = locationExtended.bodyFrameData.longAccelUnc;
+ out.bodyFrameData.latAccelUnc = locationExtended.bodyFrameData.latAccelUnc;
+ out.bodyFrameData.vertAccelUnc = locationExtended.bodyFrameData.vertAccelUnc;
+ out.bodyFrameData.yawRateUnc = locationExtended.bodyFrameData.yawRateUnc;
+ out.bodyFrameData.pitchUnc = locationExtended.bodyFrameData.pitchUnc;
+
+ out.bodyFrameDataExt.pitchRate = locationExtended.bodyFrameDataExt.pitchRate;
+ out.bodyFrameDataExt.pitchRateUnc = locationExtended.bodyFrameDataExt.pitchRateUnc;
+ out.bodyFrameDataExt.roll = locationExtended.bodyFrameDataExt.roll;
+ out.bodyFrameDataExt.rollUnc = locationExtended.bodyFrameDataExt.rollUnc;
+ out.bodyFrameDataExt.rollRate = locationExtended.bodyFrameDataExt.rollRate;
+ out.bodyFrameDataExt.rollRateUnc = locationExtended.bodyFrameDataExt.rollRateUnc;
+ out.bodyFrameDataExt.yaw = locationExtended.bodyFrameDataExt.yaw;
+ out.bodyFrameDataExt.yawUnc = locationExtended.bodyFrameDataExt.yawUnc;
+ }
+
+ // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
+ out.gnssSystemTime = locationExtended.gnssSystemTime;
+
+ if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
+ out.leapSeconds = locationExtended.leapSeconds;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
+ out.timeUncMs = locationExtended.timeUncMs;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
+ out.calibrationConfidence = locationExtended.calibrationConfidence;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
+ out.calibrationStatus = locationExtended.calibrationStatus;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
+ out.locOutputEngType = locationExtended.locOutputEngType;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
+ out.locOutputEngMask = locationExtended.locOutputEngMask;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT;
+ out.conformityIndex = locationExtended.conformityIndex;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT;
+ out.llaVRPBased = locationExtended.llaVRPBased;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT;
+ // copy over east, north and up vrp based velocity
+ out.enuVelocityVRPBased[0] = locationExtended.enuVelocityVRPBased[0];
+ out.enuVelocityVRPBased[1] = locationExtended.enuVelocityVRPBased[1];
+ out.enuVelocityVRPBased[2] = locationExtended.enuVelocityVRPBased[2];
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT;
+ out.drSolutionStatusMask = locationExtended.drSolutionStatusMask;
+ }
+
+ if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED & locationExtended.flags) {
+ out.flags |= GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT;
+ out.altitudeAssumed = locationExtended.altitudeAssumed;
+ }
+
+ out.flags |= GNSS_LOCATION_INFO_SESSION_STATUS_BIT;
+ out.sessionStatus = status;
+}
+
+inline uint32_t
+GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
+{
+ switch (suplVersion) {
+ case GNSS_CONFIG_SUPL_VERSION_2_0_4:
+ return 0x00020004;
+ case GNSS_CONFIG_SUPL_VERSION_2_0_0:
+ return 0x00020000;
+ case GNSS_CONFIG_SUPL_VERSION_2_0_2:
+ return 0x00020002;
+ case GNSS_CONFIG_SUPL_VERSION_1_0_0:
+ default:
+ return 0x00010000;
+ }
+}
+
+uint32_t
+GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
+{
+ uint32_t mask = 0;
+ if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
+ mask |= (1<<0);
+ }
+ if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
+ mask |= (1<<1);
+ }
+ if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
+ mask |= (1<<2);
+ }
+ if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
+ mask |= (1<<3);
+ }
+ return mask;
+}
+
+uint32_t
+GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
+{
+ uint32_t mask = 0;
+ if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
+ mask |= (1<<0);
+ }
+ if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
+ mask |= (1<<1);
+ }
+ if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
+ mask |= (1<<2);
+ }
+ if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
+ mask |= (1<<3);
+ }
+ return mask;
+}
+
+uint32_t
+GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
+{
+ uint32_t mask = 0;
+ if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
+ mask |= (1<<0);
+ }
+ if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
+ mask |= (1<<1);
+ }
+ if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
+ mask |= (1<<2);
+ }
+ if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
+ mask |= (1<<3);
+ }
+ return mask;
+}
+
+uint32_t
+GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
+{
+ switch (emergencyPdnForEmergencySupl) {
+ case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
+ return 1;
+ case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
+ default:
+ return 0;
+ }
+}
+
+uint32_t
+GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
+{
+ switch (suplEmergencyServices) {
+ case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
+ return 1;
+ case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
+ default:
+ return 0;
+ }
+}
+
+uint32_t
+GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
+{
+ uint32_t mask = 0;
+ if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
+ mask |= (1<<0);
+ }
+ if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
+ mask |= (1<<1);
+ }
+ return mask;
+}
+
+void
+GnssAdapter::readConfigCommand()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgReadConfig : public LocMsg {
+ GnssAdapter* mAdapter;
+ ContextBase& mContext;
+ inline MsgReadConfig(GnssAdapter* adapter,
+ ContextBase& context) :
+ LocMsg(),
+ mAdapter(adapter),
+ mContext(context) {}
+ inline virtual void proc() const {
+ static bool confReadDone = false;
+ if (!confReadDone) {
+ confReadDone = true;
+ // reads config into mContext->mGps_conf
+ mContext.readConfig();
+
+ uint32_t allowFlpNetworkFixes = 0;
+ static const loc_param_s_type flp_conf_param_table[] =
+ {
+ {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
+ };
+ UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
+ LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
+ mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
+ }
+ }
+ };
+
+ if (mContext != NULL) {
+ sendMsg(new MsgReadConfig(this, *mContext));
+ }
+}
+
+void
+GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
+{
+ if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
+ char serverUrl[MAX_URL_LEN] = {};
+ int32_t length = -1;
+ const char noHost[] = "NONE";
+
+ if ((NULL == server) || (server[0] == 0) ||
+ (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
+ serverUrl[0] = '\0';
+ length = 0;
+ } else if (port > 0) {
+ length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
+ }
+ if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
+ LOC_LOGe("Invalid type=%d", type);
+ } else if (length >= 0) {
+ if (LOC_AGPS_SUPL_SERVER == type) {
+ getServerUrl().assign(serverUrl);
+ strlcpy(ContextBase::mGps_conf.SUPL_HOST,
+ (nullptr == server) ? serverUrl : server,
+ LOC_MAX_PARAM_STRING);
+ ContextBase::mGps_conf.SUPL_PORT = port;
+ } else {
+ if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
+ getMoServerUrl().assign(serverUrl);
+ }
+ }
+ }
+ }
+}
+
+void
+GnssAdapter::setConfig()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ // set nmea mask type
+ uint32_t mask = 0;
+ if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
+ mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
+ if (ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
+ mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
+ }
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
+ mask |= LOC_NMEA_MASK_DEBUG_V02;
+ }
+ if (mNmeaMask != mask) {
+ mNmeaMask = mask;
+ if (mNmeaMask) {
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if ((it->second.gnssNmeaCb != nullptr)) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
+ LOC_REGISTRATION_MASK_ENABLED);
+ break;
+ }
+ }
+ }
+ }
+
+ std::string oldMoServerUrl = getMoServerUrl();
+ setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
+ ContextBase::mGps_conf.SUPL_PORT,
+ LOC_AGPS_SUPL_SERVER);
+ setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
+ ContextBase::mGps_conf.MO_SUPL_PORT,
+ LOC_AGPS_MO_SUPL_SERVER);
+
+ // inject the configurations into modem
+ loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
+ loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
+
+ //cache the injected configuration with GnssConfigRequested struct
+ GnssConfig gnssConfigRequested = {};
+ gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
+ GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
+ 1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
+ ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
+ NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
+ 2. P behavior. This is identified by mSupportNfwControl being 0. In this case
+ ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
+ the "mask" for NI. There are two subcases:
+ a. Location enabled in GUI (1 == getAfwControlId()). We need to set
+ the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
+ b. Location disabled in GUI (0 == getAfwControlId()). We need to set
+ the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
+ specific)
+ */
+ if (mSupportNfwControl || (0 == getAfwControlId())) {
+ gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
+ } else {
+ gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ }
+ gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
+ GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
+ GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
+ gnssConfigRequested.suplVersion = mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
+ gnssConfigRequested.lppProfileMask = gpsConf.LPP_PROFILE;
+ gnssConfigRequested.aGlonassPositionProtocolMask = gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
+ if (gpsConf.LPPE_CP_TECHNOLOGY) {
+ gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
+ gnssConfigRequested.lppeControlPlaneMask =
+ mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
+ }
+
+ if (gpsConf.LPPE_UP_TECHNOLOGY) {
+ gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
+ gnssConfigRequested.lppeUserPlaneMask =
+ mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
+ }
+ gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
+ mBlacklistedSvIds.end());
+ mLocApi->sendMsg(new LocApiMsg(
+ [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable {
+ gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
+
+ // set nmea mask type
+ uint32_t mask = 0;
+ if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
+ mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
+ if (gpsConf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
+ mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
+ }
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
+ mask |= LOC_NMEA_MASK_DEBUG_V02;
+ }
+
+ if (mask != 0) {
+ mLocApi->setNMEATypesSync(mask);
+ }
+
+ // load tunc configuration from config file on first boot-up,
+ // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
+ if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
+ mLocConfigInfo.tuncConfigInfo.isValid = true;
+ mLocConfigInfo.tuncConfigInfo.enable =
+ (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1);
+ mLocConfigInfo.tuncConfigInfo.tuncThresholdMs =
+ (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
+ mLocConfigInfo.tuncConfigInfo.energyBudget =
+ gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
+ }
+
+ mLocApi->setConstrainedTuncMode(
+ mLocConfigInfo.tuncConfigInfo.enable,
+ mLocConfigInfo.tuncConfigInfo.tuncThresholdMs,
+ mLocConfigInfo.tuncConfigInfo.energyBudget);
+
+ // load pace configuration from config file on first boot-up,
+ // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false
+ if (mLocConfigInfo.paceConfigInfo.isValid == false) {
+ mLocConfigInfo.paceConfigInfo.isValid = true;
+ mLocConfigInfo.paceConfigInfo.enable =
+ (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1);
+ }
+ mLocApi->setPositionAssistedClockEstimatorMode(
+ mLocConfigInfo.paceConfigInfo.enable);
+
+ // we do not support control robust location from gps.conf
+ if (mLocConfigInfo.robustLocationConfigInfo.isValid == true) {
+ mLocApi->configRobustLocation(
+ mLocConfigInfo.robustLocationConfigInfo.enable,
+ mLocConfigInfo.robustLocationConfigInfo.enableFor911);
+ }
+
+ if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
+ sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
+ sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
+ mLocApi->setSensorPropertiesSync(
+ sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
+ sapConf.GYRO_BIAS_RANDOM_WALK,
+ sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
+ sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
+ sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
+ sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
+ sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
+ }
+ mLocApi->setSensorPerfControlConfigSync(
+ sapConf.SENSOR_CONTROL_MODE,
+ sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
+ sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
+ sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
+ sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
+ sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
+ sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
+ sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
+ sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
+ sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
+ } ));
+ // deal with Measurement Corrections
+ if (true == mIsMeasCorrInterfaceOpen) {
+ initMeasCorr(true);
+ }
+}
+
+std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
+ GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
+ loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
+ size_t index = 0;
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ std::vector<LocationError> errsList = {err};
+ if (count > 0) {
+ errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
+ }
+
+ std::string serverUrl = getServerUrl();
+ std::string moServerUrl = getMoServerUrl();
+
+ int serverUrlLen = serverUrl.length();
+ int moServerUrlLen = moServerUrl.length();
+
+ if (!ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
+ LOC_LOGd("AGPS_CONFIG_INJECT is 0. Not setting flags for AGPS configurations");
+ gnssConfigRequested.flags &= ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
+ GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
+ GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT);
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags &
+ GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
+ GNSS_ASSISTANCE_TYPE_SUPL) {
+ err = mLocApi->setServerSync(
+ serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ if (0 != oldMoServerUrl.compare(moServerUrl)) {
+ LocationError locErr =
+ mLocApi->setServerSync(moServerUrl.c_str(),
+ moServerUrlLen,
+ LOC_AGPS_MO_SUPL_SERVER);
+ if (locErr != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
+ moServerUrl.c_str());
+ }
+ }
+ } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
+ GNSS_ASSISTANCE_TYPE_C2K) {
+ struct in_addr addr;
+ struct hostent* hp;
+ bool resolveAddrSuccess = true;
+
+ hp = gethostbyname(
+ gnssConfigNeedEngineUpdate.assistanceServer.hostName);
+ if (hp != NULL) { /* DNS OK */
+ memcpy(&addr, hp->h_addr_list[0], hp->h_length);
+ } else {
+ /* Try IP representation */
+ if (inet_aton(
+ gnssConfigNeedEngineUpdate.assistanceServer.hostName,
+ &addr) == 0) {
+ /* IP not valid */
+ LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
+ __func__,
+ gnssConfigNeedEngineUpdate.assistanceServer.hostName);
+ if (index < count) {
+ errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ resolveAddrSuccess = false;
+ }
+ }
+
+ if (resolveAddrSuccess) {
+ unsigned int ip = htonl(addr.s_addr);
+ err = mLocApi->setServerSync(ip,
+ gnssConfigNeedEngineUpdate.assistanceServer.port,
+ LOC_AGPS_CDMA_PDE_SERVER);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfileMask);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ err = mLocApi->setLPPeProtocolCpSync(
+ gnssConfigRequested.lppeControlPlaneMask);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ err = mLocApi->setLPPeProtocolUpSync(
+ gnssConfigRequested.lppeUserPlaneMask);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags &
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ err = mLocApi->setAGLONASSProtocolSync(
+ gnssConfigRequested.aGlonassPositionProtocolMask);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ // Check if feature is supported
+ if (!ContextBase::isFeatureSupported(
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ LOC_LOGe("Feature constellation enablement not supported.");
+ err = LOCATION_ERROR_NOT_SUPPORTED;
+ } else {
+ // Send the SV ID Config to Modem
+ mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
+ gnssConfigRequested.blacklistedSvIds.end());
+ err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
+ if (LOCATION_ERROR_SUCCESS != err) {
+ LOC_LOGe("Failed to send config to modem, err %d", err);
+ }
+ }
+ if (index < count) {
+ errsList[index] = err;
+ }
+ index++;
+ }
+ if (gnssConfigRequested.flags &
+ GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ if (gnssConfigNeedEngineUpdate.flags &
+ GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ err = mLocApi->setEmergencyExtensionWindowSync(
+ gnssConfigRequested.emergencyExtensionSeconds);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ }
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+ GnssConfig gnssConfig = {};
+ gnssConfig.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
+ gnssConfig.minSvElevation = gnssConfigRequested.minSvElevation;
+ err = mLocApi->setParameterSync(gnssConfig);
+ if (index < count) {
+ errsList[index] = err;
+ }
+ index++;
+ }
+
+ return errsList;
+}
+
+uint32_t*
+GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config)
+{
+ // count the number of bits set
+ GnssConfigFlagsMask flagsCopy = config.flags;
+ size_t count = 0;
+ while (flagsCopy > 0) {
+ if (flagsCopy & 1) {
+ count++;
+ }
+ flagsCopy >>= 1;
+ }
+ std::string idsString = "[";
+ uint32_t* ids = NULL;
+ if (count > 0) {
+ ids = new uint32_t[count];
+ if (ids == nullptr) {
+ LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+ return nullptr;
+ }
+ for (size_t i=0; i < count; ++i) {
+ ids[i] = generateSessionId();
+ IF_LOC_LOGD {
+ idsString += std::to_string(ids[i]) + " ";
+ }
+ }
+ }
+ idsString += "]";
+
+ LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
+
+ struct MsgGnssUpdateConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ GnssConfig mConfig;
+ size_t mCount;
+ uint32_t* mIds;
+ inline MsgGnssUpdateConfig(GnssAdapter& adapter,
+ LocApiBase& api,
+ GnssConfig config,
+ uint32_t* ids,
+ size_t count) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mConfig(config),
+ mCount(count),
+ mIds(nullptr) {
+ if (mCount > 0) {
+ mIds = new uint32_t[count];
+ if (mIds) {
+ for (uint32_t index = 0; index < count; index++) {
+ mIds[index] = ids[index];
+ }
+ } else {
+ LOC_LOGe("memory allocation for mIds failed");
+ }
+ }
+ }
+
+ inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
+ MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
+ obj.mIds, obj.mCount) {}
+
+ inline virtual ~MsgGnssUpdateConfig()
+ {
+ if (nullptr != mIds) delete[] mIds;
+ }
+
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
+ return;
+ }
+ GnssAdapter& adapter = mAdapter;
+ size_t countOfConfigs = mCount;
+ GnssConfig gnssConfigRequested = mConfig;
+ GnssConfig gnssConfigNeedEngineUpdate = mConfig;
+
+ std::vector<uint32_t> sessionIds;
+ sessionIds.assign(mIds, mIds + mCount);
+ std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
+ int index = 0;
+ bool needSuspendResume = false;
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
+
+ newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
+ ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
+ /* If we get here it means that the changes in the framework to request for
+ 'P' behavior were made, and therefore we need to "behave" as in 'P'
+ However, we need to determine if enableCommand function has already been
+ called, since it could get called before this function.*/
+ if (0 != mAdapter.getAfwControlId()) {
+ /* enableCommand function has already been called since getAfwControlId
+ returns non zero. Now there are two possible cases:
+ 1. This is the first time this function is called
+ (mSupportNfwControl is true). We need to behave as in 'P', but
+ for the first time, meaning MO was enabled, but NI was not, so
+ we need to unlock NI
+ 2. This is not the first time this function is called, meaning we
+ are already behaving as in 'P'. No need to update the configuration
+ in this case (return to 'P' code) */
+ if (mAdapter.mSupportNfwControl) {
+ // case 1 above
+ newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ } else {
+ // case 2 above
+ gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
+ }
+ }
+ gnssConfigRequested.gpsLock = newGpsLock;
+ mAdapter.mSupportNfwControl = false;
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ uint32_t newSuplVersion =
+ mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
+ ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
+ mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
+ mConfig.assistanceServer.port,
+ LOC_AGPS_SUPL_SERVER);
+ } else {
+ LOC_LOGE("%s]: Not a valid gnss assistance type %u",
+ __func__, mConfig.assistanceServer.type);
+ errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
+ gnssConfigNeedEngineUpdate.flags &=
+ ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
+ }
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ uint32_t newLppProfileMask = gnssConfigRequested.lppProfileMask;
+ ContextBase::mGps_conf.LPP_PROFILE = newLppProfileMask;
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ uint32_t newLppeControlPlaneMask =
+ mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
+ ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ uint32_t newLppeUserPlaneMask =
+ mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
+ ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
+ index++;
+ }
+ if (gnssConfigRequested.flags &
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ uint32_t newAGloProtMask =
+ mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
+ ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ uint32_t newEP4ES = mAdapter.convertEP4ES(
+ gnssConfigRequested.emergencyPdnForEmergencySupl);
+ if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
+ ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
+ }
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ uint32_t newSuplEs = mAdapter.convertSuplEs(
+ gnssConfigRequested.suplEmergencyServices);
+ if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
+ ContextBase::mGps_conf.SUPL_ES = newSuplEs;
+ }
+ index++;
+ }
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
+ ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
+ mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+ index++;
+ }
+
+ if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+ needSuspendResume = true;
+ index++;
+ }
+
+ if (needSuspendResume == true) {
+ mAdapter.suspendSessions();
+ }
+ LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
+ *adapter.getContext(),
+ [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
+
+ std::vector<uint32_t> ids(sessionIds);
+ adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
+ });
+
+ mApi.sendMsg(new LocApiMsg(
+ [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
+ countOfConfigs, configCollectiveResponse, errs] () mutable {
+ std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
+ gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
+
+ configCollectiveResponse->returnToSender(errsList);
+ }));
+
+ if (needSuspendResume == true) {
+ mAdapter.restartSessions();
+ }
+ }
+ };
+
+ if (NULL != ids) {
+ sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
+ } else {
+ LOC_LOGE("%s]: No GNSS config items to update", __func__);
+ }
+
+ return ids;
+}
+
+void
+GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
+{
+ // Clear the existing config
+ memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
+
+ // Convert the sv id lists to masks
+ bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
+
+ // Now send to Modem if conversion successful
+ if (convertSuccess) {
+ gnssSvIdConfigUpdate();
+ } else {
+ LOC_LOGe("convertToGnssSvIdConfig failed");
+ }
+}
+
+void
+GnssAdapter::gnssSvIdConfigUpdate()
+{
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+ ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+ mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+ mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+ mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+ // Now set required blacklisted SVs
+ mLocApi->setBlacklistSv(mGnssSvIdConfig);
+}
+
+LocationError
+GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
+{
+ // Clear the existing config
+ memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
+
+ // Convert the sv id lists to masks
+ convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
+
+ // Now send to Modem
+ return gnssSvIdConfigUpdateSync();
+}
+
+LocationError
+GnssAdapter::gnssSvIdConfigUpdateSync()
+{
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+ ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+ mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+ mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+ mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+
+ // Now set required blacklisted SVs
+ return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
+}
+
+void
+GnssAdapter::gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse)
+{
+ LOC_LOGd("secondary band config, size %d, enabled constellation 0x%" PRIx64 ","
+ "disabled constellation 0x%" PRIx64 "", mGnssSeconaryBandConfig.size,
+ mGnssSeconaryBandConfig.enabledSvTypesMask,
+ mGnssSeconaryBandConfig.blacklistedSvTypesMask);
+ if (mGnssSeconaryBandConfig.size == sizeof(mGnssSeconaryBandConfig)) {
+ // Now set required secondary band config
+ mLocApi->configConstellationMultiBand(mGnssSeconaryBandConfig, locApiResponse);
+ }
+}
+
+uint32_t*
+GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
+
+ // count the number of bits set
+ GnssConfigFlagsMask flagsCopy = configMask;
+ size_t count = 0;
+ while (flagsCopy > 0) {
+ if (flagsCopy & 1) {
+ count++;
+ }
+ flagsCopy >>= 1;
+ }
+ std::string idsString = "[";
+ uint32_t* ids = NULL;
+ if (count > 0) {
+ ids = new uint32_t[count];
+ if (nullptr == ids) {
+ LOC_LOGe("new allocation failed, fatal error.");
+ return nullptr;
+ }
+ for (size_t i=0; i < count; ++i) {
+ ids[i] = generateSessionId();
+ IF_LOC_LOGD {
+ idsString += std::to_string(ids[i]) + " ";
+ }
+ }
+ }
+ idsString += "]";
+
+ LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
+
+ struct MsgGnssGetConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ GnssConfigFlagsMask mConfigMask;
+ uint32_t* mIds;
+ size_t mCount;
+ inline MsgGnssGetConfig(GnssAdapter& adapter,
+ LocApiBase& api,
+ GnssConfigFlagsMask configMask,
+ uint32_t* ids,
+ size_t count) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mConfigMask(configMask),
+ mCount(count),
+ mIds(nullptr) {
+ if (mCount > 0) {
+ mIds = new uint32_t[count];
+ if (mIds) {
+ for (uint32_t index = 0; index < count; index++) {
+ mIds[index] = ids[index];
+ }
+ } else {
+ LOC_LOGe("memory allocation for mIds failed");
+ }
+ }
+ }
+
+ inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
+ MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
+ obj.mIds, obj.mCount) {}
+
+ inline virtual ~MsgGnssGetConfig()
+ {
+ if (nullptr != mIds) delete[] mIds;
+ }
+ inline virtual void proc() const {
+ if (!mAdapter.isEngineCapabilitiesKnown()) {
+ mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
+ return;
+ }
+ LocationError* errs = new LocationError[mCount];
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ uint32_t index = 0;
+
+ if (nullptr == errs) {
+ LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+ return;
+ }
+
+ if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
+ err = LOCATION_ERROR_NOT_SUPPORTED;
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
+ // Check if feature is supported
+ if (!ContextBase::isFeatureSupported(
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ LOC_LOGe("Feature not supported.");
+ err = LOCATION_ERROR_NOT_SUPPORTED;
+ } else {
+ // Send request to Modem to fetch the config
+ mApi.getBlacklistSv();
+ err = LOCATION_ERROR_SUCCESS;
+ }
+ if (index < mCount) {
+ errs[index++] = err;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
+ err = LOCATION_ERROR_NOT_SUPPORTED;
+ if (index < mCount) {
+ errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ }
+ if (mConfigMask & GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT) {
+ uint32_t sessionId = *(mIds+index);
+ LocApiResponse* locApiResponse =
+ new LocApiResponse(*mAdapter.getContext(),
+ [this, sessionId] (LocationError err) {
+ mAdapter.reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+ } else {
+ mApi.getRobustLocationConfig(sessionId, locApiResponse);
+ }
+ }
+
+ if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT) {
+ uint32_t sessionId = *(mIds+index);
+ LocApiResponse* locApiResponse =
+ new LocApiResponse(*mAdapter.getContext(),
+ [this, sessionId] (LocationError err) {
+ mAdapter.reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+ } else {
+ mApi.getMinGpsWeek(sessionId, locApiResponse);
+ }
+ }
+
+ if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
+ uint32_t sessionId = *(mIds+index);
+ LocApiResponse* locApiResponse =
+ new LocApiResponse(*mAdapter.getContext(),
+ [this, sessionId] (LocationError err) {
+ mAdapter.reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
+ } else {
+ mApi.getParameter(sessionId, GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT,
+ locApiResponse);
+ }
+ }
+
+ mAdapter.reportResponse(index, errs, mIds);
+ delete[] errs;
+
+ }
+ };
+
+ if (NULL != ids) {
+ sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
+ } else {
+ LOC_LOGe("No GNSS config items to Get");
+ }
+
+ return ids;
+}
+
+bool
+GnssAdapter::convertToGnssSvIdConfig(
+ const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
+{
+ bool retVal = false;
+ config.size = sizeof(GnssSvIdConfig);
+
+ // Empty vector => Clear any previous blacklisted SVs
+ if (0 == blacklistedSvIds.size()) {
+ config.gloBlacklistSvMask = 0;
+ config.bdsBlacklistSvMask = 0;
+ config.qzssBlacklistSvMask = 0;
+ config.galBlacklistSvMask = 0;
+ config.sbasBlacklistSvMask = 0;
+ config.navicBlacklistSvMask = 0;
+ retVal = true;
+ } else {
+ // Parse the vector and convert SV IDs to mask values
+ for (GnssSvIdSource source : blacklistedSvIds) {
+ uint64_t* svMaskPtr = NULL;
+ GnssSvId initialSvId = 0;
+ uint16_t svIndexOffset = 0;
+ switch(source.constellation) {
+ case GNSS_SV_TYPE_GLONASS:
+ svMaskPtr = &config.gloBlacklistSvMask;
+ initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ svMaskPtr = &config.bdsBlacklistSvMask;
+ initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ svMaskPtr = &config.qzssBlacklistSvMask;
+ initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ svMaskPtr = &config.galBlacklistSvMask;
+ initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ // SBAS does not support enable/disable whole constellation
+ // so do not set up svTypeMask for SBAS
+ svMaskPtr = &config.sbasBlacklistSvMask;
+ // SBAS currently has two ranges, [120, 158] and [183, 191]
+ if (0 == source.svId) {
+ LOC_LOGd("blacklist all SBAS SV");
+ } else if (source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID) {
+ // handle SV id in range [183, 191]
+ initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
+ svIndexOffset = GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
+ } else if ((source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID) &&
+ (source.svId < (GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID +
+ GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH))){
+ // handle SV id in range of [120, 158]
+ initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID;
+ } else {
+ LOC_LOGe("invalid SBAS sv id %d", source.svId);
+ svMaskPtr = nullptr;
+ }
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ svMaskPtr = &config.navicBlacklistSvMask;
+ initialSvId = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID;
+ break;
+ default:
+ break;
+ }
+
+ if (NULL == svMaskPtr) {
+ LOC_LOGe("Invalid constellation %d", source.constellation);
+ } else {
+ // SV ID 0 = All SV IDs
+ if (0 == source.svId) {
+ *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
+ LOC_LOGe("Invalid sv id %d for sv type %d",
+ source.svId, source.constellation);
+ } else {
+ uint32_t shiftCnt = source.svId + svIndexOffset - initialSvId;
+ *svMaskPtr |= (1ULL << shiftCnt);
+ }
+ }
+ }
+
+ // Return true if any one source is valid
+ if (0 != config.gloBlacklistSvMask ||
+ 0 != config.bdsBlacklistSvMask ||
+ 0 != config.galBlacklistSvMask ||
+ 0 != config.qzssBlacklistSvMask ||
+ 0 != config.sbasBlacklistSvMask ||
+ 0 != config.navicBlacklistSvMask) {
+ retVal = true;
+ }
+ }
+
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+ ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+ config.bdsBlacklistSvMask, config.gloBlacklistSvMask,
+ config.qzssBlacklistSvMask, config.galBlacklistSvMask,
+ config.sbasBlacklistSvMask, config.navicBlacklistSvMask);
+
+ return retVal;
+}
+
+void GnssAdapter::convertFromGnssSvIdConfig(
+ const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds)
+{
+ // Convert blacklisted SV mask values to vectors
+ if (svConfig.bdsBlacklistSvMask) {
+ convertGnssSvIdMaskToList(
+ svConfig.bdsBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
+ }
+ if (svConfig.galBlacklistSvMask) {
+ convertGnssSvIdMaskToList(
+ svConfig.galBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
+ }
+ if (svConfig.gloBlacklistSvMask) {
+ convertGnssSvIdMaskToList(
+ svConfig.gloBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
+ }
+ if (svConfig.qzssBlacklistSvMask) {
+ convertGnssSvIdMaskToList(
+ svConfig.qzssBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
+ }
+ if (svConfig.sbasBlacklistSvMask) {
+ // SBAS - SV 120 to 158, maps to 0 to 38
+ // SV 183 to 191, maps to 39 to 47
+ uint64_t sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
+ // operate on 120 and 158 first
+ sbasBlacklistSvMask <<= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
+ sbasBlacklistSvMask >>= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
+ convertGnssSvIdMaskToList(
+ sbasBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID, GNSS_SV_TYPE_SBAS);
+ // operate on the second range
+ sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
+ sbasBlacklistSvMask >>= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
+ convertGnssSvIdMaskToList(
+ sbasBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID, GNSS_SV_TYPE_SBAS);
+ }
+ if (svConfig.navicBlacklistSvMask) {
+ convertGnssSvIdMaskToList(
+ svConfig.navicBlacklistSvMask, blacklistedSvIds,
+ GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID, GNSS_SV_TYPE_NAVIC);
+ }
+}
+
+void GnssAdapter::convertGnssSvIdMaskToList(
+ uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
+ GnssSvId initialSvId, GnssSvType svType)
+{
+ GnssSvIdSource source = {};
+ source.size = sizeof(GnssSvIdSource);
+ source.constellation = svType;
+
+ // SV ID 0 => All SV IDs in mask
+ if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
+ LOC_LOGd("blacklist all SVs in constellation %d", source.constellation);
+ source.svId = 0;
+ svIds.push_back(source);
+ return;
+ }
+
+ // Convert each bit in svIdMask to vector entry
+ uint32_t bitNumber = 0;
+ while (svIdMask > 0) {
+ if (svIdMask & 0x1) {
+ source.svId = bitNumber + initialSvId;
+ // SBAS has two ranges:
+ // SBAS - SV 120 to 158, maps to 0 to 38
+ // SV 183 to 191, maps to 39 to 47
+ // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120
+ // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
+ // #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183
+ if (svType == GNSS_SV_TYPE_SBAS) {
+ if (bitNumber >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH) {
+ source.svId = bitNumber - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH +
+ GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
+ }
+ }
+ svIds.push_back(source);
+ }
+ bitNumber++;
+ svIdMask >>= 1;
+ }
+}
+
+void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
+{
+ struct MsgReportGnssSvIdConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ const GnssSvIdConfig mConfig;
+ inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
+ const GnssSvIdConfig& config) :
+ LocMsg(),
+ mAdapter(adapter),
+ mConfig(config) {}
+ inline virtual void proc() const {
+ mAdapter.reportGnssSvIdConfig(mConfig);
+ }
+ };
+
+ sendMsg(new MsgReportGnssSvIdConfig(*this, config));
+}
+
+void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
+{
+ GnssConfig config = {};
+ config.size = sizeof(GnssConfig);
+
+ // Invoke control clients config callback
+ if (nullptr != mControlCallbacks.gnssConfigCb &&
+ svIdConfig.size == sizeof(GnssSvIdConfig)) {
+
+ convertFromGnssSvIdConfig(svIdConfig, config.blacklistedSvIds);
+ if (config.blacklistedSvIds.size() > 0) {
+ config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
+ }
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 ", "
+ "qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
+ svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
+ svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask,
+ svIdConfig.sbasBlacklistSvMask, svIdConfig.navicBlacklistSvMask);
+ // use 0 session id to indicate that receiver does not yet care about session id
+ mControlCallbacks.gnssConfigCb(0, config);
+ } else {
+ LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
+ }
+}
+
+void
+GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
+{
+ struct MsgGnssUpdateSvTypeConfig : public LocMsg {
+ GnssAdapter* mAdapter;
+ LocApiBase* mApi;
+ GnssSvTypeConfig mConfig;
+ inline MsgGnssUpdateSvTypeConfig(
+ GnssAdapter* adapter,
+ LocApiBase* api,
+ GnssSvTypeConfig& config) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mConfig(config) {}
+ inline virtual void proc() const {
+ if (!mAdapter->isEngineCapabilitiesKnown()) {
+ mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
+ return;
+ }
+ // Check if feature is supported
+ if (!ContextBase::isFeatureSupported(
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ LOC_LOGe("Feature not supported.");
+ } else {
+ // Send update request to modem
+ mAdapter->gnssSvTypeConfigUpdate(mConfig);
+ }
+ }
+ };
+
+ sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
+}
+
+void
+GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
+{
+ // Gather bits removed from enabled mask
+ GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
+ (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
+ // Send reset if any constellation is removed from the enabled list
+ bool sendReset = (enabledRemoved != 0);
+ // Save new config and update
+ gnssSetSvTypeConfig(config);
+ gnssSvTypeConfigUpdate(sendReset);
+}
+
+void
+GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
+{
+ LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
+ ", sendReset %d",
+ mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
+ mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
+
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+ ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
+ mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+ mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+ mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+
+ LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
+ ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
+ mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
+ mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
+ mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
+
+ if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
+
+ if (sendReset) {
+ mLocApi->resetConstellationControl();
+ }
+
+ GnssSvIdConfig blacklistConfig = {};
+ // Revert to previously blacklisted SVs for each enabled constellation
+ blacklistConfig = mGnssSvIdConfig;
+ // Blacklist all SVs for each disabled constellation
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
+ blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ }
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
+ blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ }
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
+ blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ }
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
+ blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ }
+ if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
+ blacklistConfig.navicBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
+ }
+ }
+
+ // Send blacklist info
+ mLocApi->setBlacklistSv(blacklistConfig);
+
+ // Send only enabled constellation config
+ if (mGnssSvTypeConfig.enabledSvTypesMask) {
+ GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
+ svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
+ mLocApi->setConstellationControl(svTypeConfig);
+ }
+ }
+}
+
+void
+GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
+{
+ struct MsgGnssGetSvTypeConfig : public LocMsg {
+ GnssAdapter* mAdapter;
+ LocApiBase* mApi;
+ GnssSvTypeConfigCallback mCallback;
+ inline MsgGnssGetSvTypeConfig(
+ GnssAdapter* adapter,
+ LocApiBase* api,
+ GnssSvTypeConfigCallback callback) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mCallback(callback) {}
+ inline virtual void proc() const {
+ if (!mAdapter->isEngineCapabilitiesKnown()) {
+ mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
+ return;
+ }
+ if (!ContextBase::isFeatureSupported(
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ LOC_LOGe("Feature not supported.");
+ } else {
+ // Save the callback
+ mAdapter->gnssSetSvTypeConfigCallback(mCallback);
+ // Send GET request to modem
+ mApi->getConstellationControl();
+ }
+ }
+ };
+
+ sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
+}
+
+void
+GnssAdapter::gnssResetSvTypeConfigCommand()
+{
+ struct MsgGnssResetSvTypeConfig : public LocMsg {
+ GnssAdapter* mAdapter;
+ LocApiBase* mApi;
+ inline MsgGnssResetSvTypeConfig(
+ GnssAdapter* adapter,
+ LocApiBase* api) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api) {}
+ inline virtual void proc() const {
+ if (!mAdapter->isEngineCapabilitiesKnown()) {
+ mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
+ return;
+ }
+ if (!ContextBase::isFeatureSupported(
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ LOC_LOGe("Feature not supported.");
+ } else {
+ // Reset constellation config
+ mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
+ // Re-enforce SV blacklist config
+ mAdapter->gnssSvIdConfigUpdate();
+ // Send reset request to modem
+ mApi->resetConstellationControl();
+ }
+ }
+ };
+
+ sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
+}
+
+void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
+{
+ struct MsgReportGnssSvTypeConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ const GnssSvTypeConfig mConfig;
+ inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
+ const GnssSvTypeConfig& config) :
+ LocMsg(),
+ mAdapter(adapter),
+ mConfig(config) {}
+ inline virtual void proc() const {
+ mAdapter.reportGnssSvTypeConfig(mConfig);
+ }
+ };
+
+ sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
+}
+
+void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
+{
+ // Invoke Get SV Type Callback
+ if (NULL != mGnssSvTypeConfigCb &&
+ config.size == sizeof(GnssSvTypeConfig)) {
+ LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
+ config.blacklistedSvTypesMask, config.enabledSvTypesMask);
+ mGnssSvTypeConfigCb(config);
+ } else {
+ LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
+ }
+}
+
+void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
+ struct timespec bootDeleteAidingDataTime;
+ int64_t bootDeleteTimeMs;
+ if (clock_gettime(CLOCK_BOOTTIME, &bootDeleteAidingDataTime) == 0) {
+ bootDeleteTimeMs = bootDeleteAidingDataTime.tv_sec * 1000000;
+ int64_t diffTimeBFirSecDelete = bootDeleteTimeMs - mLastDeleteAidingDataTime;
+ if (diffTimeBFirSecDelete > DELETE_AIDING_DATA_EXPECTED_TIME_MS) {
+ mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);
+ }));
+ mLastDeleteAidingDataTime = bootDeleteTimeMs;
+ }
+ }
+}
+
+uint32_t
+GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
+{
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGD("%s]: id %u", __func__, sessionId);
+
+ struct MsgDeleteAidingData : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ GnssAidingData mData;
+ inline MsgDeleteAidingData(GnssAdapter& adapter,
+ uint32_t sessionId,
+ GnssAidingData& data) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mData(data) {}
+ inline virtual void proc() const {
+ if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
+ mAdapter.deleteAidingData(mData, mSessionId);
+ SystemStatus* s = mAdapter.getSystemStatus();
+ if ((nullptr != s) && (mData.deleteAll)) {
+ s->setDefaultGnssEngineStates();
+ }
+ }
+
+ bool retVal = mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
+ // When SPE engine is invoked, responseCb will be invoked
+ // from QMI Loc API call.
+ // When SPE engine is not invoked, we also need to deliver responseCb
+ if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) == 0) {
+ LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+ if (retVal == true) {
+ err = LOCATION_ERROR_SUCCESS;
+ }
+ mAdapter.reportResponse(err, mSessionId);
+ }
+ }
+ };
+
+ sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
+ return sessionId;
+}
+
+void
+GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
+{
+ LOC_LOGD("%s] enabled:%d", __func__, enabled);
+
+ struct UpdateXtraThrottleMsg : public LocMsg {
+ GnssAdapter& mAdapter;
+ const bool mEnabled;
+ inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
+ LocMsg(),
+ mAdapter(adapter),
+ mEnabled(enabled) {}
+ inline virtual void proc() const {
+ mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
+ }
+ };
+
+ sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
+}
+
+void
+GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
+{
+ LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
+ __func__, latitude, longitude, accuracy);
+
+ struct MsgInjectLocation : public LocMsg {
+ LocApiBase& mApi;
+ ContextBase& mContext;
+ BlockCPIInfo& mBlockCPI;
+ double mLatitude;
+ double mLongitude;
+ float mAccuracy;
+ bool mOnDemandCpi;
+ inline MsgInjectLocation(LocApiBase& api,
+ ContextBase& context,
+ BlockCPIInfo& blockCPIInfo,
+ double latitude,
+ double longitude,
+ float accuracy,
+ bool onDemandCpi) :
+ LocMsg(),
+ mApi(api),
+ mContext(context),
+ mBlockCPI(blockCPIInfo),
+ mLatitude(latitude),
+ mLongitude(longitude),
+ mAccuracy(accuracy),
+ mOnDemandCpi(onDemandCpi) {}
+ inline virtual void proc() const {
+ if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
+ (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
+ (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
+
+ LOC_LOGD("%s]: positon injection blocked: lat: %f, lon: %f, accuracy: %f",
+ __func__, mLatitude, mLongitude, mAccuracy);
+
+ } else {
+ mApi.injectPosition(mLatitude, mLongitude, mAccuracy, mOnDemandCpi);
+ }
+ }
+ };
+
+ sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
+ latitude, longitude, accuracy, mOdcpiRequestActive));
+}
+
+void
+GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
+{
+ LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
+ locationInfo.location.latitude, locationInfo.location.longitude,
+ locationInfo.location.accuracy, locationInfo.location.techMask);
+
+ struct MsgInjectLocationExt : public LocMsg {
+ LocApiBase& mApi;
+ ContextBase& mContext;
+ GnssLocationInfoNotification mLocationInfo;
+ inline MsgInjectLocationExt(LocApiBase& api,
+ ContextBase& context,
+ GnssLocationInfoNotification locationInfo) :
+ LocMsg(),
+ mApi(api),
+ mContext(context),
+ mLocationInfo(locationInfo) {}
+ inline virtual void proc() const {
+ // false to indicate for none-ODCPI
+ mApi.injectPosition(mLocationInfo, false);
+ }
+ };
+
+ sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
+}
+
+void
+GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
+{
+ LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
+ __func__, (long long)time, (long long)timeReference, uncertainty);
+
+ struct MsgInjectTime : public LocMsg {
+ LocApiBase& mApi;
+ ContextBase& mContext;
+ int64_t mTime;
+ int64_t mTimeReference;
+ int32_t mUncertainty;
+ inline MsgInjectTime(LocApiBase& api,
+ ContextBase& context,
+ int64_t time,
+ int64_t timeReference,
+ int32_t uncertainty) :
+ LocMsg(),
+ mApi(api),
+ mContext(context),
+ mTime(time),
+ mTimeReference(timeReference),
+ mUncertainty(uncertainty) {}
+ inline virtual void proc() const {
+ mApi.setTime(mTime, mTimeReference, mUncertainty);
+ }
+ };
+
+ sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
+}
+
+// This command is to called to block the position to be injected to the modem.
+// This can happen for network position that comes from modem.
+void
+GnssAdapter::blockCPICommand(double latitude, double longitude,
+ float accuracy, int blockDurationMsec,
+ double latLonDiffThreshold)
+{
+ struct MsgBlockCPI : public LocMsg {
+ BlockCPIInfo& mDstCPIInfo;
+ BlockCPIInfo mSrcCPIInfo;
+
+ inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
+ BlockCPIInfo& srcCPIInfo) :
+ mDstCPIInfo(dstCPIInfo),
+ mSrcCPIInfo(srcCPIInfo) {}
+ inline virtual void proc() const {
+ // in the same hal thread, save the cpi to be blocked
+ // the global variable
+ mDstCPIInfo = mSrcCPIInfo;
+ }
+ };
+
+ // construct the new block CPI info and queue on the same thread
+ // for processing
+ BlockCPIInfo blockCPIInfo;
+ blockCPIInfo.latitude = latitude;
+ blockCPIInfo.longitude = longitude;
+ blockCPIInfo.accuracy = accuracy;
+ blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
+ blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
+
+ LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
+ // send a message to record down the coarse position
+ // to be blocked from injection in the master copy (mBlockCPIInfo)
+ sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
+}
+
+void
+GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) {
+ if (POWER_STATE_UNKNOWN != systemPowerState) {
+ mSystemPowerState = systemPowerState;
+ mLocApi->updateSystemPowerState(mSystemPowerState);
+ }
+}
+
+void
+GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) {
+ LOC_LOGd("power event %d", systemPowerState);
+
+ struct MsgUpdatePowerState : public LocMsg {
+ GnssAdapter& mAdapter;
+ PowerStateType mSystemPowerState;
+
+ inline MsgUpdatePowerState(GnssAdapter& adapter,
+ PowerStateType systemPowerState) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSystemPowerState(systemPowerState) {}
+ inline virtual void proc() const {
+ mAdapter.updateSystemPowerState(mSystemPowerState);
+ }
+ };
+
+ sendMsg(new MsgUpdatePowerState(*this, systemPowerState));
+}
+
+void
+GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+ struct MsgAddClient : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocationAPI* mClient;
+ const LocationCallbacks mCallbacks;
+ inline MsgAddClient(GnssAdapter& adapter,
+ LocationAPI* client,
+ const LocationCallbacks& callbacks) :
+ LocMsg(),
+ mAdapter(adapter),
+ mClient(client),
+ mCallbacks(callbacks) {}
+ inline virtual void proc() const {
+ // check whether we need to notify client of cached location system info
+ mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
+ mAdapter.saveClient(mClient, mCallbacks);
+ }
+ };
+
+ sendMsg(new MsgAddClient(*this, client, callbacks));
+}
+
+void
+GnssAdapter::stopClientSessions(LocationAPI* client)
+{
+ LOC_LOGD("%s]: client %p", __func__, client);
+
+ /* Time-based Tracking */
+ std::vector<LocationSessionKey> vTimeBasedTrackingClient;
+ for (auto it : mTimeBasedTrackingSessions) {
+ if (client == it.first.client) {
+ vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
+ }
+ }
+ for (auto key : vTimeBasedTrackingClient) {
+ stopTimeBasedTrackingMultiplex(key.client, key.id);
+ eraseTrackingSession(key.client, key.id);
+ }
+
+ /* Distance-based Tracking */
+ for (auto it = mDistanceBasedTrackingSessions.begin();
+ it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
+ if (client == it->first.client) {
+ mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
+ [this, client, id=it->first.id] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ eraseTrackingSession(client, id);
+ }
+ }
+ ));
+ }
+ ++it; // increment only when not erasing an iterator
+ }
+
+}
+
+void
+GnssAdapter::updateClientsEventMask()
+{
+ // need to register for leap second info
+ // for proper nmea generation
+ LOC_API_ADAPTER_EVENT_MASK_T mask = LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO |
+ LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (it->second.trackingCb != nullptr ||
+ it->second.gnssLocationInfoCb != nullptr ||
+ it->second.engineLocationsInfoCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
+ }
+ if (it->second.gnssSvCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
+ }
+ if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
+ mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
+ }
+ if (it->second.gnssMeasurementsCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
+ }
+ if (it->second.gnssDataCb != nullptr) {
+ mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
+ mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
+ updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
+ }
+ }
+
+ /*
+ ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
+ ** when QDR is enabled (e.g.: either enabled via conf file or
+ ** engine hub is loaded successfully).
+ ** Note: this need to be called from msg queue thread.
+ */
+ if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
+ (true == initEngHubProxy())) {
+ mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
+ mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
+ mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
+ mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
+
+ // Nhz measurement bit is set based on callback from loc eng hub
+ // for Nhz engines.
+ mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT);
+
+ LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
+ mask);
+ }
+
+ if (mAgpsManager.isRegistered()) {
+ mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
+ }
+ // Add ODCPI handling
+ if (nullptr != mOdcpiRequestCb) {
+ mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
+ }
+
+ // need to register for leap second info
+ // for proper nmea generation
+ mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
+
+ // always register for NI NOTIFY VERIFY to handle internally in HAL
+ mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
+
+ // Enable the latency report
+ if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) {
+ if (mLogger.isLogEnabled()) {
+ mask |= LOC_API_ADAPTER_BIT_LATENCY_INFORMATION;
+ }
+ }
+
+ updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
+}
+
+void
+GnssAdapter::handleEngineUpEvent()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgHandleEngineUpEvent : public LocMsg {
+ GnssAdapter& mAdapter;
+ inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ virtual void proc() const {
+ mAdapter.setEngineCapabilitiesKnown(true);
+ mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+ // must be called only after capabilities are known
+ mAdapter.setConfig();
+ mAdapter.gnssSvIdConfigUpdate();
+ mAdapter.gnssSvTypeConfigUpdate();
+ mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
+ mAdapter.gnssSecondaryBandConfigUpdate();
+ // start CDFW service
+ mAdapter.initCDFWService();
+ // restart sessions
+ mAdapter.restartSessions(true);
+ for (auto msg: mAdapter.mPendingMsgs) {
+ mAdapter.sendMsg(msg);
+ }
+ mAdapter.mPendingMsgs.clear();
+ }
+ };
+
+ readConfigCommand();
+ sendMsg(new MsgHandleEngineUpEvent(*this));
+}
+
+void
+GnssAdapter::restartSessions(bool modemSSR)
+{
+ LOC_LOGi(":enter");
+
+ if (modemSSR) {
+ // odcpi session is no longer active after restart
+ mOdcpiRequestActive = false;
+ }
+
+ // SPE will be restarted now, so set this variable to false.
+ mSPEAlreadyRunningAtHighestInterval = false;
+
+ if (false == mTimeBasedTrackingSessions.empty()) {
+ // inform engine hub that GNSS session is about to start
+ mEngHubProxy->gnssSetFixMode(mLocPositionMode);
+ mEngHubProxy->gnssStartFix();
+ checkUpdateDgnssNtrip(false);
+ }
+
+ checkAndRestartSPESession();
+}
+
+void GnssAdapter::checkAndRestartSPESession()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ // SPE will be restarted now, so set this variable to false.
+ mSPEAlreadyRunningAtHighestInterval = false;
+
+ checkAndRestartTimeBasedSession();
+
+ for (auto it = mDistanceBasedTrackingSessions.begin();
+ it != mDistanceBasedTrackingSessions.end(); ++it) {
+ mLocApi->startDistanceBasedTracking(it->first.id, it->second,
+ new LocApiResponse(*getContext(),
+ [] (LocationError /*err*/) {}));
+ }
+}
+
+// suspend all on-going sessions
+void
+GnssAdapter::suspendSessions()
+{
+ LOC_LOGi(":enter");
+
+ if (!mTimeBasedTrackingSessions.empty()) {
+ // inform engine hub that GNSS session has stopped
+ mEngHubProxy->gnssStopFix();
+ mLocApi->stopFix(nullptr);
+ if (isDgnssNmeaRequired()) {
+ mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+ }
+ stopDgnssNtrip();
+ mSPEAlreadyRunningAtHighestInterval = false;
+ }
+}
+
+void GnssAdapter::checkAndRestartTimeBasedSession()
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ if (!mTimeBasedTrackingSessions.empty()) {
+ // get the LocationOptions that has the smallest interval, which should be the active one
+ TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
+ TrackingOptions highestPowerTrackingOptions;
+ memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
+ memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
+ for (auto it = mTimeBasedTrackingSessions.begin();
+ it != mTimeBasedTrackingSessions.end(); ++it) {
+ // size of zero means we havent set it yet
+ if (0 == smallestIntervalOptions.size ||
+ it->second.minInterval < smallestIntervalOptions.minInterval) {
+ smallestIntervalOptions = it->second;
+ }
+ GnssPowerMode powerMode = it->second.powerMode;
+ // Size of zero means we havent set it yet
+ if (0 == highestPowerTrackingOptions.size ||
+ (GNSS_POWER_MODE_INVALID != powerMode &&
+ powerMode < highestPowerTrackingOptions.powerMode)) {
+ highestPowerTrackingOptions = it->second;
+ }
+ }
+
+ highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
+ // want to run SPE session at a fixed min interval in some automotive scenarios
+ if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) {
+ mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
+ }
+ }
+}
+
+LocationCapabilitiesMask
+GnssAdapter::getCapabilities()
+{
+ LocationCapabilitiesMask mask = 0;
+ uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
+ // time based tracking always supported
+ mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
+ // geofence always supported
+ mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
+ if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
+ }
+ if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
+ }
+ if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) {
+ mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
+ LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
+ }
+ if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
+ mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
+ }
+ if (ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) {
+ mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT;
+ }
+ if (ContextBase::gnssConstellationConfig()) {
+ mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
+ mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
+ mask |= LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT;
+ }
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_AGPM_V02)) {
+ mask |= LOCATION_CAPABILITIES_AGPM_BIT;
+ }
+ //Get QWES feature status mask
+ mask |= ContextBase::getQwesFeatureStatus();
+ return mask;
+}
+
+void
+GnssAdapter::notifyClientOfCachedLocationSystemInfo(
+ LocationAPI* client, const LocationCallbacks& callbacks) {
+
+ if (mLocSystemInfo.systemInfoMask) {
+ // client need to be notified if client has not yet previously registered
+ // for the info but now register for it.
+ bool notifyClientOfSystemInfo = false;
+ // check whether we need to notify client of cached location system info
+ //
+ // client need to be notified if client has not yet previously registered
+ // for the info but now register for it.
+ if (callbacks.locationSystemInfoCb) {
+ notifyClientOfSystemInfo = true;
+ auto it = mClientData.find(client);
+ if (it != mClientData.end()) {
+ LocationCallbacks oldCallbacks = it->second;
+ if (oldCallbacks.locationSystemInfoCb) {
+ notifyClientOfSystemInfo = false;
+ }
+ }
+ }
+
+ if (notifyClientOfSystemInfo) {
+ callbacks.locationSystemInfoCb(mLocSystemInfo);
+ }
+ }
+}
+
+bool
+GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
+}
+
+bool
+GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
+}
+
+bool
+GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client)
+{
+ bool allowed = false;
+ auto it = mClientData.find(client);
+ if (it != mClientData.end()) {
+ if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
+ it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb ||
+ it->second.gnssDataCb || it->second.gnssSvCb || it->second.gnssNmeaCb) {
+ allowed = true;
+ } else {
+ LOC_LOGi("missing right callback to start tracking")
+ }
+ } else {
+ LOC_LOGi("client %p not found", client)
+ }
+ return allowed;
+}
+
+bool
+GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
+}
+
+void
+GnssAdapter::reportPowerStateIfChanged()
+{
+ bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
+ !mDistanceBasedTrackingSessions.empty();
+ if (newPowerOn != mPowerOn) {
+ mPowerOn = newPowerOn;
+ if (mPowerStateCb != nullptr) {
+ mPowerStateCb(mPowerOn);
+ }
+ }
+}
+
+void
+GnssAdapter::getPowerStateChangesCommand(std::function<void(bool)> powerStateCb)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgReportLocation : public LocMsg {
+ GnssAdapter& mAdapter;
+ std::function<void(bool)> mPowerStateCb;
+ inline MsgReportLocation(GnssAdapter& adapter,
+ std::function<void(bool)> powerStateCb) :
+ LocMsg(),
+ mAdapter(adapter),
+ mPowerStateCb(powerStateCb) {}
+ inline virtual void proc() const {
+ mAdapter.savePowerStateCallback(mPowerStateCb);
+ mPowerStateCb(mAdapter.getPowerState());
+ }
+ };
+
+ sendMsg(new MsgReportLocation(*this, powerStateCb));
+}
+
+void
+GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& options)
+{
+ LocationSessionKey key(client, sessionId);
+ if ((options.minDistance > 0) &&
+ ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
+ mDistanceBasedTrackingSessions[key] = options;
+ } else {
+ mTimeBasedTrackingSessions[key] = options;
+ }
+ reportPowerStateIfChanged();
+}
+
+void
+GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
+{
+ LocationSessionKey key(client, sessionId);
+ auto it = mTimeBasedTrackingSessions.find(key);
+ if (it != mTimeBasedTrackingSessions.end()) {
+ mTimeBasedTrackingSessions.erase(it);
+ } else {
+ auto itr = mDistanceBasedTrackingSessions.find(key);
+ if (itr != mDistanceBasedTrackingSessions.end()) {
+ mDistanceBasedTrackingSessions.erase(itr);
+ }
+ }
+ reportPowerStateIfChanged();
+}
+
+bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
+ if (!mLocPositionMode.equals(mode)) {
+ mLocPositionMode = mode;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void
+GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
+{
+ LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
+
+ auto it = mClientData.find(client);
+ if (it != mClientData.end() && it->second.responseCb != nullptr) {
+ it->second.responseCb(err, sessionId);
+ } else {
+ LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
+ }
+}
+
+void
+GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
+{
+ LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
+
+ if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
+ mControlCallbacks.responseCb(err, sessionId);
+ } else {
+ LOC_LOGW("%s]: control client response callback not found", __func__);
+ }
+}
+
+void
+GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
+{
+ IF_LOC_LOGD {
+ std::string idsString = "[";
+ std::string errsString = "[";
+ if (NULL != ids && NULL != errs) {
+ for (size_t i=0; i < count; ++i) {
+ idsString += std::to_string(ids[i]) + " ";
+ errsString += std::to_string(errs[i]) + " ";
+ }
+ }
+ idsString += "]";
+ errsString += "]";
+
+ LOC_LOGD("%s]: ids %s errs %s",
+ __func__, idsString.c_str(), errsString.c_str());
+ }
+
+ if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
+ mControlCallbacks.collectiveResponseCb(count, errs, ids);
+ } else {
+ LOC_LOGW("%s]: control client callback not found", __func__);
+ }
+}
+
+uint32_t
+GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
+{
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
+ __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
+ options.powerMode, options.tbm);
+
+ struct MsgStartTracking : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ mutable TrackingOptions mOptions;
+ inline MsgStartTracking(GnssAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId,
+ TrackingOptions options) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId),
+ mOptions(options) {}
+ inline virtual void proc() const {
+ // distance based tracking will need to know engine capabilities before it can start
+ if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
+ mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ if (!mAdapter.hasCallbacksToStartTracking(mClient)) {
+ err = LOCATION_ERROR_CALLBACK_MISSING;
+ } else if (0 == mOptions.size) {
+ err = LOCATION_ERROR_INVALID_PARAMETER;
+ } else {
+ if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
+ mOptions.minInterval = MIN_TRACKING_INTERVAL;
+ }
+ if (mOptions.minDistance > 0 &&
+ ContextBase::isMessageSupported(
+ LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+ mApi.startDistanceBasedTracking(mSessionId, mOptions,
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
+ (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ mAdapter.eraseTrackingSession(mClient, mSessionId);
+ }
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }));
+ } else {
+ if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
+ mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
+ LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
+ mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
+ mOptions.powerMode = GNSS_POWER_MODE_M2;
+ }
+ // Api doesn't support multiple clients for time based tracking, so mutiplex
+ bool reportToClientWithNoWait =
+ mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+
+ if (reportToClientWithNoWait) {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
+ }
+ }
+ }
+ }
+ };
+
+ sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
+ return sessionId;
+
+}
+
+bool
+GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& options)
+{
+ bool reportToClientWithNoWait = true;
+
+ if (mTimeBasedTrackingSessions.empty()) {
+ /*Reset previous NMEA reported time stamp */
+ mPrevNmeaRptTimeNsec = 0;
+ startTimeBasedTracking(client, sessionId, options);
+ // need to wait for QMI callback
+ reportToClientWithNoWait = false;
+ } else {
+ // find the smallest interval and powerMode
+ TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
+ GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
+ memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
+ for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
+ // if not set or there is a new smallest interval, then set the new interval
+ if (0 == multiplexedOptions.size ||
+ it->second.minInterval < multiplexedOptions.minInterval) {
+ multiplexedOptions = it->second;
+ }
+ // if session is not the one we are updating and either powerMode
+ // is not set or there is a new smallest powerMode, then set the new powerMode
+ if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
+ it->second.powerMode < multiplexedPowerMode) {
+ multiplexedPowerMode = it->second.powerMode;
+ }
+ }
+ bool updateOptions = false;
+ // if session we are starting has smaller interval then next smallest
+ if (options.minInterval < multiplexedOptions.minInterval) {
+ multiplexedOptions.minInterval = options.minInterval;
+ updateOptions = true;
+ }
+
+ // if session we are starting has smaller powerMode then next smallest
+ if (options.powerMode < multiplexedPowerMode) {
+ multiplexedOptions.powerMode = options.powerMode;
+ updateOptions = true;
+ }
+ if (updateOptions) {
+ // restart time based tracking with the newly updated options
+
+ startTimeBasedTracking(client, sessionId, multiplexedOptions);
+ // need to wait for QMI callback
+ reportToClientWithNoWait = false;
+ }
+ // else part: no QMI call is made, need to report back to client right away
+ }
+
+ return reportToClientWithNoWait;
+}
+
+void
+GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& trackingOptions)
+{
+ LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
+ trackingOptions.minInterval, trackingOptions.minDistance,
+ trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
+ LocPosMode locPosMode = {};
+ convertOptions(locPosMode, trackingOptions);
+ // save position mode parameters
+ setLocPositionMode(locPosMode);
+ // inform engine hub that GNSS session is about to start
+ mEngHubProxy->gnssSetFixMode(mLocPositionMode);
+ mEngHubProxy->gnssStartFix();
+
+ // want to run SPE session at a fixed min interval in some automotive scenarios
+ // use a local copy of TrackingOptions as the TBF may get modified in the
+ // checkAndSetSPEToRunforNHz function
+ TrackingOptions tempOptions(trackingOptions);
+ if (!checkAndSetSPEToRunforNHz(tempOptions)) {
+ mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
+ [this, client, sessionId] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ eraseTrackingSession(client, sessionId);
+ } else {
+ checkUpdateDgnssNtrip(false);
+ }
+
+ reportResponse(client, err, sessionId);
+ }
+ ));
+ } else {
+ reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
+ }
+
+}
+
+void
+GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
+{
+ LocPosMode locPosMode = {};
+ convertOptions(locPosMode, updatedOptions);
+ // save position mode parameters
+ setLocPositionMode(locPosMode);
+
+ // inform engine hub that GNSS session is about to start
+ mEngHubProxy->gnssSetFixMode(mLocPositionMode);
+ mEngHubProxy->gnssStartFix();
+
+ // want to run SPE session at a fixed min interval in some automotive scenarios
+ // use a local copy of TrackingOptions as the TBF may get modified in the
+ // checkAndSetSPEToRunforNHz function
+ TrackingOptions tempOptions(updatedOptions);
+ if(!checkAndSetSPEToRunforNHz(tempOptions)) {
+ mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
+ [this, client, sessionId, oldOptions] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS != err) {
+ // restore the old LocationOptions
+ saveTrackingSession(client, sessionId, oldOptions);
+ }
+ reportResponse(client, err, sessionId);
+ }
+ ));
+ } else {
+ reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
+ }
+}
+
+void
+GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
+ TrackingOptions& options)
+{
+ LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
+ __func__, client, id, options.minInterval, options.mode);
+
+ struct MsgUpdateTracking : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ mutable TrackingOptions mOptions;
+ inline MsgUpdateTracking(GnssAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId,
+ TrackingOptions options) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId),
+ mOptions(options) {}
+ inline virtual void proc() const {
+ // distance based tracking will need to know engine capabilities before it can start
+ if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
+ mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
+ return;
+ }
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
+ bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
+ if (!isTimeBased && !isDistanceBased) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ } else if (0 == mOptions.size) {
+ err = LOCATION_ERROR_INVALID_PARAMETER;
+ }
+ if (LOCATION_ERROR_SUCCESS != err) {
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ } else {
+ if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
+ mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
+ LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
+ mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
+ mOptions.powerMode = GNSS_POWER_MODE_M2;
+ }
+ if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
+ mOptions.minInterval = MIN_TRACKING_INTERVAL;
+ }
+ // Now update session as required
+ if (isTimeBased && mOptions.minDistance > 0) {
+ // switch from time based to distance based
+ // Api doesn't support multiple clients for time based tracking, so mutiplex
+ bool reportToClientWithNoWait =
+ mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
+ // erases the time based Session
+ mAdapter.eraseTrackingSession(mClient, mSessionId);
+ if (reportToClientWithNoWait) {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
+ }
+ // saves as distance based Session
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+ mApi.startDistanceBasedTracking(mSessionId, mOptions,
+ new LocApiResponse(*mAdapter.getContext(),
+ [] (LocationError /*err*/) {}));
+ } else if (isDistanceBased && mOptions.minDistance == 0) {
+ // switch from distance based to time based
+ mAdapter.eraseTrackingSession(mClient, mSessionId);
+ mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
+ *mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
+ mClient = mClient] (LocationError /*err*/) {
+ // Api doesn't support multiple clients for time based tracking,
+ // so mutiplex
+ bool reportToClientWithNoWait =
+ mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
+ mOptions);
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+
+ if (reportToClientWithNoWait) {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
+ }
+ }));
+ } else if (isTimeBased) {
+ // update time based tracking
+ // Api doesn't support multiple clients for time based tracking, so mutiplex
+ bool reportToClientWithNoWait =
+ mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+
+ if (reportToClientWithNoWait) {
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }
+ } else if (isDistanceBased) {
+ // restart distance based tracking
+ mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
+ *mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
+ mClient = mClient, &mApi = mApi] (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mApi.startDistanceBasedTracking(mSessionId, mOptions,
+ new LocApiResponse(*mAdapter.getContext(),
+ [&mAdapter, mClient, mSessionId, mOptions]
+ (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
+ }
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }));
+ }
+ }));
+ }
+ }
+ }
+ };
+
+ sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
+}
+
+bool
+GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
+ const TrackingOptions& trackingOptions)
+{
+ bool reportToClientWithNoWait = true;
+
+ LocationSessionKey key(client, id);
+ // get the session we are updating
+ auto it = mTimeBasedTrackingSessions.find(key);
+
+ // cache the clients existing LocationOptions
+ TrackingOptions oldOptions = it->second;
+
+ // if session we are updating exists and the minInterval or powerMode has changed
+ if (it != mTimeBasedTrackingSessions.end() &&
+ (it->second.minInterval != trackingOptions.minInterval ||
+ it->second.powerMode != trackingOptions.powerMode)) {
+ // find the smallest interval and powerMode, other than the session we are updating
+ TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
+ GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
+ memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
+ for (auto it2 = mTimeBasedTrackingSessions.begin();
+ it2 != mTimeBasedTrackingSessions.end(); ++it2) {
+ // if session is not the one we are updating and either interval
+ // is not set or there is a new smallest interval, then set the new interval
+ if (it2->first != key && (0 == multiplexedOptions.size ||
+ it2->second.minInterval < multiplexedOptions.minInterval)) {
+ multiplexedOptions = it2->second;
+ }
+ // if session is not the one we are updating and either powerMode
+ // is not set or there is a new smallest powerMode, then set the new powerMode
+ if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
+ it2->second.powerMode < multiplexedPowerMode)) {
+ multiplexedPowerMode = it2->second.powerMode;
+ }
+ // else part: no QMI call is made, need to report back to client right away
+ }
+ bool updateOptions = false;
+ // if session we are updating has smaller interval then next smallest
+ if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
+ multiplexedOptions.minInterval = trackingOptions.minInterval;
+ updateOptions = true;
+ }
+ // if session we are updating has smaller powerMode then next smallest
+ if (trackingOptions.powerMode < multiplexedPowerMode) {
+ multiplexedOptions.powerMode = trackingOptions.powerMode;
+ updateOptions = true;
+ }
+ // if only one session exists, then tracking should be updated with it
+ if (1 == mTimeBasedTrackingSessions.size()) {
+ multiplexedOptions = trackingOptions;
+ updateOptions = true;
+ }
+ if (updateOptions) {
+ // restart time based tracking with the newly updated options
+ updateTracking(client, id, multiplexedOptions, oldOptions);
+ // need to wait for QMI callback
+ reportToClientWithNoWait = false;
+ }
+ }
+
+ return reportToClientWithNoWait;
+}
+
+void
+GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
+{
+ LOC_LOGD("%s]: client %p id %u", __func__, client, id);
+
+ struct MsgStopTracking : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ inline MsgStopTracking(GnssAdapter& adapter,
+ LocApiBase& api,
+ LocationAPI* client,
+ uint32_t sessionId) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mClient(client),
+ mSessionId(sessionId) {}
+ inline virtual void proc() const {
+ bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
+ bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
+ if (isTimeBased || isDistanceBased) {
+ if (isTimeBased) {
+ // Api doesn't support multiple clients for time based tracking, so mutiplex
+ bool reportToClientWithNoWait =
+ mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
+ mAdapter.eraseTrackingSession(mClient, mSessionId);
+
+ if (reportToClientWithNoWait) {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
+ }
+ } else if (isDistanceBased) {
+ mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
+ *mAdapter.getContext(),
+ [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
+ (LocationError err) {
+ if (LOCATION_ERROR_SUCCESS == err) {
+ mAdapter.eraseTrackingSession(mClient, mSessionId);
+ }
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }));
+ }
+ } else {
+ mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
+ }
+
+ }
+ };
+
+ sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
+}
+
+bool
+GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
+{
+ bool reportToClientWithNoWait = true;
+
+ if (1 == mTimeBasedTrackingSessions.size()) {
+ stopTracking(client, id);
+ // need to wait for QMI callback
+ reportToClientWithNoWait = false;
+ } else {
+ LocationSessionKey key(client, id);
+
+ // get the session we are stopping
+ auto it = mTimeBasedTrackingSessions.find(key);
+ if (it != mTimeBasedTrackingSessions.end()) {
+ // find the smallest interval and powerMode, other than the session we are stopping
+ TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
+ GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
+ memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
+ for (auto it2 = mTimeBasedTrackingSessions.begin();
+ it2 != mTimeBasedTrackingSessions.end(); ++it2) {
+ // if session is not the one we are stopping and either interval
+ // is not set or there is a new smallest interval, then set the new interval
+ if (it2->first != key && (0 == multiplexedOptions.size ||
+ it2->second.minInterval < multiplexedOptions.minInterval)) {
+ multiplexedOptions = it2->second;
+ }
+ // if session is not the one we are stopping and either powerMode
+ // is not set or there is a new smallest powerMode, then set the new powerMode
+ if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
+ it2->second.powerMode < multiplexedPowerMode)) {
+ multiplexedPowerMode = it2->second.powerMode;
+ }
+ }
+ // if session we are stopping has smaller interval then next smallest or
+ // if session we are stopping has smaller powerMode then next smallest
+ if (it->second.minInterval < multiplexedOptions.minInterval ||
+ it->second.powerMode < multiplexedPowerMode) {
+ multiplexedOptions.powerMode = multiplexedPowerMode;
+ // restart time based tracking with the newly updated options
+ startTimeBasedTracking(client, id, multiplexedOptions);
+ // need to wait for QMI callback
+ reportToClientWithNoWait = false;
+ }
+ // else part: no QMI call is made, need to report back to client right away
+ }
+ }
+ return reportToClientWithNoWait;
+}
+
+void
+GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
+{
+ // inform engine hub that GNSS session has stopped
+ mEngHubProxy->gnssStopFix();
+
+ mLocApi->stopFix(new LocApiResponse(*getContext(),
+ [this, client, id] (LocationError err) {
+ reportResponse(client, err, id);
+ }));
+
+ if (isDgnssNmeaRequired()) {
+ mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+ }
+ stopDgnssNtrip();
+
+ mSPEAlreadyRunningAtHighestInterval = false;
+}
+
+bool
+GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
+{
+ auto it = mClientData.find(client);
+ return (it != mClientData.end() && it->second.gnssNiCb);
+}
+
+void
+GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
+ uint32_t id,
+ GnssNiResponse response)
+{
+ LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
+
+ struct MsgGnssNiResponse : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocationAPI* mClient;
+ uint32_t mSessionId;
+ GnssNiResponse mResponse;
+ inline MsgGnssNiResponse(GnssAdapter& adapter,
+ LocationAPI* client,
+ uint32_t sessionId,
+ GnssNiResponse response) :
+ LocMsg(),
+ mAdapter(adapter),
+ mClient(client),
+ mSessionId(sessionId),
+ mResponse(response) {}
+ inline virtual void proc() const {
+ NiData& niData = mAdapter.getNiData();
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ if (!mAdapter.hasNiNotifyCallback(mClient)) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ } else {
+ NiSession* pSession = NULL;
+ if (mSessionId == niData.sessionEs.reqID &&
+ NULL != niData.sessionEs.rawRequest) {
+ pSession = &niData.sessionEs;
+ // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
+ if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
+ NULL != niData.session.rawRequest) {
+ pthread_mutex_lock(&niData.session.tLock);
+ niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
+ niData.session.respRecvd = true;
+ pthread_cond_signal(&niData.session.tCond);
+ pthread_mutex_unlock(&niData.session.tLock);
+ }
+ } else if (mSessionId == niData.session.reqID &&
+ NULL != niData.session.rawRequest) {
+ pSession = &niData.session;
+ }
+
+ if (pSession) {
+ LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
+ __func__, mResponse, mSessionId);
+ pthread_mutex_lock(&pSession->tLock);
+ pSession->resp = mResponse;
+ pSession->respRecvd = true;
+ pthread_cond_signal(&pSession->tCond);
+ pthread_mutex_unlock(&pSession->tLock);
+ } else {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
+ __func__, mSessionId);
+ }
+ }
+ mAdapter.reportResponse(mClient, err, mSessionId);
+ }
+ };
+
+ sendMsg(new MsgGnssNiResponse(*this, client, id, response));
+
+}
+
+void
+GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
+{
+ LOC_LOGD("%s]: response %u", __func__, response);
+
+ struct MsgGnssNiResponse : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ const GnssNiResponse mResponse;
+ const void* mPayload;
+ inline MsgGnssNiResponse(GnssAdapter& adapter,
+ LocApiBase& api,
+ const GnssNiResponse response,
+ const void* rawRequest) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mResponse(response),
+ mPayload(rawRequest) {}
+ inline virtual ~MsgGnssNiResponse() {
+ }
+ inline virtual void proc() const {
+ mApi.informNiResponse(mResponse, mPayload);
+ }
+ };
+
+ sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
+
+}
+
+uint32_t
+GnssAdapter::enableCommand(LocationTechnologyType techType)
+{
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
+
+ struct MsgEnableGnss : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ ContextBase& mContext;
+ uint32_t mSessionId;
+ LocationTechnologyType mTechType;
+ inline MsgEnableGnss(GnssAdapter& adapter,
+ LocApiBase& api,
+ ContextBase& context,
+ uint32_t sessionId,
+ LocationTechnologyType techType) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mContext(context),
+ mSessionId(sessionId),
+ mTechType(techType) {}
+ inline virtual void proc() const {
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ uint32_t afwControlId = mAdapter.getAfwControlId();
+ if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
+ err = LOCATION_ERROR_INVALID_PARAMETER;
+ } else if (afwControlId > 0) {
+ err = LOCATION_ERROR_ALREADY_STARTED;
+ } else {
+ mContext.modemPowerVote(true);
+ mAdapter.setAfwControlId(mSessionId);
+
+ GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
+ if (mAdapter.mSupportNfwControl) {
+ ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
+ gpsLock = ContextBase::mGps_conf.GPS_LOCK;
+ }
+ mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
+ mApi.setGpsLockSync(gpsLock);
+ }));
+ mAdapter.mXtraObserver.updateLockStatus(gpsLock);
+ }
+ mAdapter.reportResponse(err, mSessionId);
+ }
+ };
+
+ if (mContext != NULL) {
+ sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
+ } else {
+ LOC_LOGE("%s]: Context is NULL", __func__);
+ }
+
+ return sessionId;
+}
+
+void
+GnssAdapter::disableCommand(uint32_t id)
+{
+ LOC_LOGD("%s]: id %u", __func__, id);
+
+ struct MsgDisableGnss : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ ContextBase& mContext;
+ uint32_t mSessionId;
+ inline MsgDisableGnss(GnssAdapter& adapter,
+ LocApiBase& api,
+ ContextBase& context,
+ uint32_t sessionId) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mContext(context),
+ mSessionId(sessionId) {}
+ inline virtual void proc() const {
+ LocationError err = LOCATION_ERROR_SUCCESS;
+ uint32_t afwControlId = mAdapter.getAfwControlId();
+ if (afwControlId != mSessionId) {
+ err = LOCATION_ERROR_ID_UNKNOWN;
+ } else {
+ mContext.modemPowerVote(false);
+ mAdapter.setAfwControlId(0);
+
+ if (mAdapter.mSupportNfwControl) {
+ /* We need to disable MO (AFW) */
+ ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
+ }
+ GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
+ mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
+ mApi.setGpsLockSync(gpsLock);
+ }));
+ mAdapter.mXtraObserver.updateLockStatus(gpsLock);
+ }
+ mAdapter.reportResponse(err, mSessionId);
+ }
+ };
+
+ if (mContext != NULL) {
+ sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
+ }
+
+}
+
+// This function computes the VRP based latitude, longitude and alittude, and
+// north, east and up velocity and save the result into EHubTechReport.
+void
+GnssAdapter::computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
+ const LeverArmConfigInfo& leverArmConfigInfo) {
+
+ float leverArm[3];
+ float rollPitchYaw[3];
+ double lla[3];
+
+ uint16_t locFlags = loc.gpsLocation.flags;
+ uint64_t locExtFlags = locExt.flags;
+
+ // check for SPE fix
+ if (!((locExtFlags & GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE) &&
+ (locExt.locOutputEngType == LOC_OUTPUT_ENGINE_SPE))){
+ LOC_LOGv("not SPE fix, return");
+ return;
+ }
+
+ // we can only do translation if we have VRP based lever ARM info
+ LeverArmTypeMask leverArmFlags = leverArmConfigInfo.leverArmValidMask;
+ if (!(leverArmFlags & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT)) {
+ LOC_LOGd("no VRP based lever ARM info");
+ return;
+ }
+
+ leverArm[0] = leverArmConfigInfo.gnssToVRP.forwardOffsetMeters;
+ leverArm[1] = leverArmConfigInfo.gnssToVRP.sidewaysOffsetMeters;
+ leverArm[2] = leverArmConfigInfo.gnssToVRP.upOffsetMeters;
+
+ if ((locFlags & LOC_GPS_LOCATION_HAS_LAT_LONG) &&
+ (locFlags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
+ (locFlags & LOCATION_HAS_BEARING_BIT)) {
+
+ lla[0] = loc.gpsLocation.latitude * DEG2RAD;
+ lla[1] = loc.gpsLocation.longitude * DEG2RAD;
+ lla[2] = loc.gpsLocation.altitude;
+
+ rollPitchYaw[0] = 0.0f;
+ rollPitchYaw[1] = 0.0f;
+ rollPitchYaw[2] = loc.gpsLocation.bearing * DEG2RAD;
+
+ loc_convert_lla_gnss_to_vrp(lla, rollPitchYaw, leverArm);
+
+ // assign the converted value into position report and
+ // set up valid mask
+ locExt.llaVRPBased.latitude = lla[0] * RAD2DEG;
+ locExt.llaVRPBased.longitude = lla[1] * RAD2DEG;
+ locExt.llaVRPBased.altitude = lla[2];
+ locExt.flags |= GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED;
+ } else {
+ LOC_LOGd("SPE fix missing latitude/longitude/alitutde");
+ return;
+ }
+}
+
+void
+GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask techMask,
+ GnssDataNotification* pDataNotify,
+ int msInWeek)
+{
+ // this position is from QMI LOC API, then send report to engine hub
+ // also, send out SPE fix promptly to the clients that have registered
+ // with SPE report
+ LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d msInWeek %d",
+ locationExtended.locOutputEngType,
+ ulpLocation.unpropagatedPosition, status, msInWeek);
+
+ struct MsgReportSPEPosition : public LocMsg {
+ GnssAdapter& mAdapter;
+ mutable UlpLocation mUlpLocation;
+ mutable GpsLocationExtended mLocationExtended;
+ enum loc_sess_status mStatus;
+ LocPosTechMask mTechMask;
+ mutable GnssDataNotification mDataNotify;
+ int mMsInWeek;
+
+ inline MsgReportSPEPosition(GnssAdapter& adapter,
+ const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask techMask,
+ GnssDataNotification dataNotify,
+ int msInWeek) :
+ LocMsg(),
+ mAdapter(adapter),
+ mUlpLocation(ulpLocation),
+ mLocationExtended(locationExtended),
+ mStatus(status),
+ mTechMask(techMask),
+ mDataNotify(dataNotify),
+ mMsInWeek(msInWeek) {}
+ inline virtual void proc() const {
+ if (mAdapter.mTimeBasedTrackingSessions.empty() &&
+ mAdapter.mDistanceBasedTrackingSessions.empty()) {
+ LOC_LOGd("reportPositionEvent, no session on-going, throw away the SPE reports");
+ return;
+ }
+
+ if (false == mUlpLocation.unpropagatedPosition && mDataNotify.size != 0) {
+ if (mMsInWeek >= 0) {
+ mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
+ mMsInWeek);
+ }
+ mAdapter.reportData(mDataNotify);
+ }
+
+ if (true == mAdapter.initEngHubProxy()){
+ // send the SPE fix to engine hub
+ mAdapter.mEngHubProxy->gnssReportPosition(mUlpLocation, mLocationExtended, mStatus);
+ // report out all SPE fix if it is not propagated, even for failed fix
+ if (false == mUlpLocation.unpropagatedPosition) {
+ EngineLocationInfo engLocationInfo = {};
+ engLocationInfo.location = mUlpLocation;
+ engLocationInfo.locationExtended = mLocationExtended;
+ engLocationInfo.sessionStatus = mStatus;
+
+ // obtain the VRP based latitude/longitude/altitude for SPE fix
+ computeVRPBasedLla(engLocationInfo.location,
+ engLocationInfo.locationExtended,
+ mAdapter.mLocConfigInfo.leverArmConfigInfo);
+ mAdapter.reportEnginePositions(1, &engLocationInfo);
+ }
+ return;
+ }
+
+ // unpropagated report: is only for engine hub to consume and no need
+ // to send out to the clients
+ if (true == mUlpLocation.unpropagatedPosition) {
+ return;
+ }
+
+ // extract bug report info - this returns true if consumed by systemstatus
+ SystemStatus* s = mAdapter.getSystemStatus();
+ if ((nullptr != s) &&
+ ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
+ s->eventPosition(mUlpLocation, mLocationExtended);
+ }
+
+ mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
+ }
+ };
+
+ if (mContext != NULL) {
+ GnssDataNotification dataNotifyCopy = {};
+ if (pDataNotify) {
+ dataNotifyCopy = *pDataNotify;
+ dataNotifyCopy.size = sizeof(dataNotifyCopy);
+ }
+ sendMsg(new MsgReportSPEPosition(*this, ulpLocation, locationExtended,
+ status, techMask, dataNotifyCopy, msInWeek));
+ }
+}
+
+void
+GnssAdapter::reportEnginePositionsEvent(unsigned int count,
+ EngineLocationInfo* locationArr)
+{
+ struct MsgReportEnginePositions : public LocMsg {
+ GnssAdapter& mAdapter;
+ unsigned int mCount;
+ EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
+ inline MsgReportEnginePositions(GnssAdapter& adapter,
+ unsigned int count,
+ EngineLocationInfo* locationArr) :
+ LocMsg(),
+ mAdapter(adapter),
+ mCount(count) {
+ if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
+ mCount = LOC_OUTPUT_ENGINE_COUNT;
+ }
+ if (mCount > 0) {
+ memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
+ }
+ }
+ inline virtual void proc() const {
+ mAdapter.reportEnginePositions(mCount, mEngLocInfo);
+ }
+ };
+
+ sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
+}
+
+bool
+GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
+ enum loc_sess_status status,
+ LocPosTechMask techMask) {
+ bool reported = false;
+
+ // if engine hub is enabled, aka, any of the engine services is enabled,
+ // then always output position reported by engine hub to requesting client
+ if (true == initEngHubProxy()) {
+ reported = true;
+ } else {
+ reported = LocApiBase::needReport(ulpLocation, status, techMask);
+ }
+ return reported;
+}
+
+bool
+GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
+ LocPosTechMask techMask) {
+ if (((LOC_SESS_INTERMEDIATE == status) && !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
+ (!getAllowFlpNetworkFixes())) ||
+ (LOC_SESS_FAILURE == status)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool
+GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.gnssLocationInfoCb == nullptr &&
+ locationCallbacks.gnssSvCb == nullptr &&
+ locationCallbacks.gnssNmeaCb == nullptr &&
+ locationCallbacks.gnssDataCb == nullptr &&
+ locationCallbacks.gnssMeasurementsCb == nullptr);
+}
+
+bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
+ const struct timespec32_t &apTimeStamp)
+{
+ bool retVal = false;
+ uint64_t currentTimeNsec = 0;
+
+ if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTimeBasedTrackingSessions.empty()) {
+ currentTimeNsec = (apTimeStamp.tv_sec * BILLION_NSEC + apTimeStamp.tv_nsec);
+ if ((GNSS_NMEA_REPORT_RATE_NHZ == ContextBase::sNmeaReportRate) ||
+ (GPS_DEFAULT_FIX_INTERVAL_MS <= mLocPositionMode.min_interval)) {
+ retVal = true;
+ } else { /*tbf is less than 1000 milli-seconds and NMEA reporting rate is set to 1Hz */
+ /* Always send NMEA string for first position report
+ * Send when gpsTimeOfWeekMs is closely aligned with integer boundary
+ */
+ if ((0 == mPrevNmeaRptTimeNsec) ||
+ (0 != gpsTimeOfWeekMs) && (NMEA_MIN_THRESHOLD_MSEC >= (gpsTimeOfWeekMs % 1000))) {
+ retVal = true;
+ } else {
+ uint64_t timeDiffMsec = ((currentTimeNsec - mPrevNmeaRptTimeNsec) / 1000000);
+ // Send when the delta time becomes >= 1 sec
+ if (NMEA_MAX_THRESHOLD_MSEC <= timeDiffMsec) {
+ retVal = true;
+ }
+ }
+ }
+ if (true == retVal) {
+ mPrevNmeaRptTimeNsec = currentTimeNsec;
+ }
+ }
+ return retVal;
+}
+
+void
+GnssAdapter::logLatencyInfo()
+{
+ if (0 == mGnssLatencyInfoQueue.size()) {
+ LOC_LOGv("mGnssLatencyInfoQueue.size is 0");
+ return;
+ }
+ mGnssLatencyInfoQueue.front().hlosQtimer5 = getQTimerTickCount();
+ if (0 == mGnssLatencyInfoQueue.front().hlosQtimer3) {
+ /* if SPE from engine hub is not reported then hlosQtimer3 = 0, set it
+ equal to hlosQtimer2 to make sense */
+ LOC_LOGv("hlosQtimer3 is 0, setting it to hlosQtimer2");
+ mGnssLatencyInfoQueue.front().hlosQtimer3 = mGnssLatencyInfoQueue.front().hlosQtimer2;
+ }
+ if (0 == mGnssLatencyInfoQueue.front().hlosQtimer4) {
+ /* if PPE from engine hub is not reported then hlosQtimer4 = 0, set it
+ equal to hlosQtimer3 to make sense */
+ LOC_LOGv("hlosQtimer4 is 0, setting it to hlosQtimer3");
+ mGnssLatencyInfoQueue.front().hlosQtimer4 = mGnssLatencyInfoQueue.front().hlosQtimer3;
+ }
+ if (mGnssLatencyInfoQueue.front().hlosQtimer4 < mGnssLatencyInfoQueue.front().hlosQtimer3) {
+ /* hlosQtimer3 is timestamped when SPE from engine hub is reported,
+ and hlosQtimer4 is timestamped when PPE from engine hub is reported.
+ The order is random though, hence making sure the timestamps are sorted */
+ LOC_LOGv("hlosQtimer4 is < hlosQtimer3, swapping them");
+ std::swap(mGnssLatencyInfoQueue.front().hlosQtimer3,
+ mGnssLatencyInfoQueue.front().hlosQtimer4);
+ }
+ LOC_LOGv("meQtimer1=%" PRIi64 " "
+ "meQtimer2=%" PRIi64 " "
+ "meQtimer3=%" PRIi64 " "
+ "peQtimer1=%" PRIi64 " "
+ "peQtimer2=%" PRIi64 " "
+ "peQtimer3=%" PRIi64 " "
+ "smQtimer1=%" PRIi64 " "
+ "smQtimer2=%" PRIi64 " "
+ "smQtimer3=%" PRIi64 " "
+ "locMwQtimer=%" PRIi64 " "
+ "hlosQtimer1=%" PRIi64 " "
+ "hlosQtimer2=%" PRIi64 " "
+ "hlosQtimer3=%" PRIi64 " "
+ "hlosQtimer4=%" PRIi64 " "
+ "hlosQtimer5=%" PRIi64 " ",
+ mGnssLatencyInfoQueue.front().meQtimer1, mGnssLatencyInfoQueue.front().meQtimer2,
+ mGnssLatencyInfoQueue.front().meQtimer3, mGnssLatencyInfoQueue.front().peQtimer1,
+ mGnssLatencyInfoQueue.front().peQtimer2, mGnssLatencyInfoQueue.front().peQtimer3,
+ mGnssLatencyInfoQueue.front().smQtimer1, mGnssLatencyInfoQueue.front().smQtimer2,
+ mGnssLatencyInfoQueue.front().smQtimer3, mGnssLatencyInfoQueue.front().locMwQtimer,
+ mGnssLatencyInfoQueue.front().hlosQtimer1, mGnssLatencyInfoQueue.front().hlosQtimer2,
+ mGnssLatencyInfoQueue.front().hlosQtimer3, mGnssLatencyInfoQueue.front().hlosQtimer4,
+ mGnssLatencyInfoQueue.front().hlosQtimer5);
+ mLogger.log(mGnssLatencyInfoQueue.front());
+ mGnssLatencyInfoQueue.pop();
+ LOC_LOGv("mGnssLatencyInfoQueue.size after pop=%zu", mGnssLatencyInfoQueue.size());
+}
+
+// only fused report (when engine hub is enabled) or
+// SPE report (when engine hub is disabled) will reach this function
+void
+GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask techMask)
+{
+ bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
+ bool reportToFlpClient = needReportForFlpClient(status, techMask);
+
+ if (reportToGnssClient || reportToFlpClient) {
+ GnssLocationInfoNotification locationInfo = {};
+ convertLocationInfo(locationInfo, locationExtended, status);
+ convertLocation(locationInfo.location, ulpLocation, locationExtended);
+ logLatencyInfo();
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if ((reportToFlpClient && isFlpClient(it->second)) ||
+ (reportToGnssClient && !isFlpClient(it->second))) {
+ if (nullptr != it->second.gnssLocationInfoCb) {
+ it->second.gnssLocationInfoCb(locationInfo);
+ } else if ((nullptr != it->second.engineLocationsInfoCb) &&
+ (false == initEngHubProxy())) {
+ // if engine hub is disabled, this is SPE fix from modem
+ // we need to mark one copy marked as fused and one copy marked as PPE
+ // and dispatch it to the engineLocationsInfoCb
+ GnssLocationInfoNotification engLocationsInfo[2];
+ engLocationsInfo[0] = locationInfo;
+ engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
+ engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
+ engLocationsInfo[1] = locationInfo;
+ it->second.engineLocationsInfoCb(2, engLocationsInfo);
+ } else if (nullptr != it->second.trackingCb) {
+ it->second.trackingCb(locationInfo.location);
+ }
+ }
+ }
+
+ mGnssSvIdUsedInPosAvail = false;
+ mGnssMbSvIdUsedInPosAvail = false;
+ if (reportToGnssClient) {
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
+ mGnssSvIdUsedInPosAvail = true;
+ mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
+ mGnssMbSvIdUsedInPosAvail = true;
+ mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
+ }
+ }
+
+ // if PACE is enabled
+ if ((true == mLocConfigInfo.paceConfigInfo.isValid) &&
+ (true == mLocConfigInfo.paceConfigInfo.enable)) {
+ // If fix has sensor contribution, and it is fused fix with DRE engine
+ // contributing to the fix, inject to modem
+ if ((LOC_POS_TECH_MASK_SENSORS & techMask) &&
+ (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT) &&
+ (locationInfo.locOutputEngType == LOC_OUTPUT_ENGINE_FUSED) &&
+ (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT) &&
+ (locationInfo.locOutputEngMask & DEAD_RECKONING_ENGINE)) {
+ mLocApi->injectPosition(locationInfo, false);
+ }
+ }
+ }
+ }
+
+ if (needToGenerateNmeaReport(locationExtended.gpsTime.gpsTimeOfWeekMs,
+ locationExtended.timeStamp.apTimeStamp)) {
+ /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
+ horReliability is not set. */
+ bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
+ (0 == ulpLocation.gpsLocation.longitude) &&
+ (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
+ uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
+ bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
+ bool isTagBlockGroupingEnabled =
+ (1 == ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED);
+ std::vector<std::string> nmeaArraystr;
+ int indexOfGGA = -1;
+ loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea,
+ custom_nmea_gga, nmeaArraystr, indexOfGGA, isTagBlockGroupingEnabled);
+ stringstream ss;
+ for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
+ ss << *itor;
+ }
+ string s = ss.str();
+ reportNmea(s.c_str(), s.length());
+
+ /* DgnssNtrip */
+ if (-1 != indexOfGGA && isDgnssNmeaRequired()) {
+ mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+ mStartDgnssNtripParams.nmea = std::move(nmeaArraystr[indexOfGGA]);
+ bool isLocationValid = (0 != ulpLocation.gpsLocation.latitude) ||
+ (0 != ulpLocation.gpsLocation.longitude);
+ checkUpdateDgnssNtrip(isLocationValid);
+ }
+ }
+}
+
+void
+GnssAdapter::reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo)
+{
+ struct MsgReportLatencyInfo : public LocMsg {
+ GnssAdapter& mAdapter;
+ GnssLatencyInfo mGnssLatencyInfo;
+ inline MsgReportLatencyInfo(GnssAdapter& adapter,
+ const GnssLatencyInfo& gnssLatencyInfo) :
+ mGnssLatencyInfo(gnssLatencyInfo),
+ mAdapter(adapter) {}
+ inline virtual void proc() const {
+ mAdapter.mGnssLatencyInfoQueue.push(mGnssLatencyInfo);
+ LOC_LOGv("mGnssLatencyInfoQueue.size after push=%zu",
+ mAdapter.mGnssLatencyInfoQueue.size());
+ }
+ };
+ sendMsg(new MsgReportLatencyInfo(*this, gnssLatencyInfo));
+}
+
+void
+GnssAdapter::reportEnginePositions(unsigned int count,
+ const EngineLocationInfo* locationArr)
+{
+ bool needReportEnginePositions = false;
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.engineLocationsInfoCb) {
+ needReportEnginePositions = true;
+ break;
+ }
+ }
+
+ GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
+ for (unsigned int i = 0; i < count; i++) {
+ const EngineLocationInfo* engLocation = (locationArr+i);
+ // if it is fused/default location, call reportPosition maintain legacy behavior
+ if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
+ (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
+ reportPosition(engLocation->location,
+ engLocation->locationExtended,
+ engLocation->sessionStatus,
+ engLocation->location.tech_mask);
+ }
+
+ if (needReportEnginePositions) {
+ convertLocationInfo(locationInfo[i], engLocation->locationExtended,
+ engLocation->sessionStatus);
+ convertLocation(locationInfo[i].location,
+ engLocation->location,
+ engLocation->locationExtended);
+ }
+ }
+
+ const EngineLocationInfo* engLocation = locationArr;
+ LOC_LOGv("engLocation->locationExtended.locOutputEngType=%d",
+ engLocation->locationExtended.locOutputEngType);
+
+ if (0 != mGnssLatencyInfoQueue.size()) {
+ if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
+ (LOC_OUTPUT_ENGINE_SPE == engLocation->locationExtended.locOutputEngType)) {
+ mGnssLatencyInfoQueue.front().hlosQtimer3 = getQTimerTickCount();
+ LOC_LOGv("SPE hlosQtimer3=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer3);
+ }
+ if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
+ (LOC_OUTPUT_ENGINE_PPE == engLocation->locationExtended.locOutputEngType)) {
+ mGnssLatencyInfoQueue.front().hlosQtimer4 = getQTimerTickCount();
+ LOC_LOGv("PPE hlosQtimer4=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer4);
+ }
+ }
+ if (needReportEnginePositions) {
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.engineLocationsInfoCb) {
+ it->second.engineLocationsInfoCb(count, locationInfo);
+ }
+ }
+ }
+}
+
+void
+GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
+ bool fromEngineHub)
+{
+ if (!fromEngineHub) {
+ mEngHubProxy->gnssReportSv(svNotify);
+ if (true == initEngHubProxy()){
+ return;
+ }
+ }
+
+ struct MsgReportSv : public LocMsg {
+ GnssAdapter& mAdapter;
+ const GnssSvNotification mSvNotify;
+ inline MsgReportSv(GnssAdapter& adapter,
+ const GnssSvNotification& svNotify) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSvNotify(svNotify) {}
+ inline virtual void proc() const {
+ mAdapter.reportSv((GnssSvNotification&)mSvNotify);
+ }
+ };
+
+ sendMsg(new MsgReportSv(*this, svNotify));
+}
+
+void
+GnssAdapter::reportSv(GnssSvNotification& svNotify)
+{
+ int numSv = svNotify.count;
+ uint16_t gnssSvId = 0;
+ uint64_t svUsedIdMask = 0;
+ for (int i=0; i < numSv; i++) {
+ svUsedIdMask = 0;
+ gnssSvId = svNotify.gnssSvs[i].svId;
+ GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
+ switch (svNotify.gnssSvs[i].type) {
+ case GNSS_SV_TYPE_GPS:
+ if (mGnssSvIdUsedInPosAvail) {
+ if (mGnssMbSvIdUsedInPosAvail) {
+ switch (signalTypeMask) {
+ case GNSS_SIGNAL_GPS_L1CA:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GPS_L1C:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GPS_L2:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GPS_L5:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
+ break;
+ }
+ } else {
+ svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
+ }
+ }
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ if (mGnssSvIdUsedInPosAvail) {
+ if (mGnssMbSvIdUsedInPosAvail) {
+ switch (signalTypeMask) {
+ case GNSS_SIGNAL_GLONASS_G1:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GLONASS_G2:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
+ break;
+ }
+ } else {
+ svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
+ }
+ }
+ // map the svid to respective constellation range 1..xx
+ // then repective constellation svUsedIdMask map correctly to svid
+ gnssSvId = gnssSvId - GLO_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ if (mGnssSvIdUsedInPosAvail) {
+ if (mGnssMbSvIdUsedInPosAvail) {
+ switch (signalTypeMask) {
+ case GNSS_SIGNAL_BEIDOU_B1I:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B1C:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2I:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2AI:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2AQ:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
+ break;
+ }
+ } else {
+ svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
+ }
+ }
+ gnssSvId = gnssSvId - BDS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ if (mGnssSvIdUsedInPosAvail) {
+ if (mGnssMbSvIdUsedInPosAvail) {
+ switch (signalTypeMask) {
+ case GNSS_SIGNAL_GALILEO_E1:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5A:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5B:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
+ break;
+ }
+ } else {
+ svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
+ }
+ }
+ gnssSvId = gnssSvId - GAL_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ if (mGnssSvIdUsedInPosAvail) {
+ if (mGnssMbSvIdUsedInPosAvail) {
+ switch (signalTypeMask) {
+ case GNSS_SIGNAL_QZSS_L1CA:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_QZSS_L1S:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_QZSS_L2:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
+ break;
+ case GNSS_SIGNAL_QZSS_L5:
+ svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
+ break;
+ }
+ } else {
+ svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
+ }
+ }
+ gnssSvId = gnssSvId - QZSS_SV_PRN_MIN + 1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ if (mGnssSvIdUsedInPosAvail) {
+ svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
+ }
+ gnssSvId = gnssSvId - NAVIC_SV_PRN_MIN + 1;
+ break;
+ default:
+ svUsedIdMask = 0;
+ break;
+ }
+
+ // If SV ID was used in previous position fix, then set USED_IN_FIX
+ // flag, else clear the USED_IN_FIX flag.
+ if (svFitsMask(svUsedIdMask, gnssSvId) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
+ svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
+ }
+ }
+
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.gnssSvCb) {
+ it->second.gnssSvCb(svNotify);
+ }
+ }
+
+ if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
+ !mTimeBasedTrackingSessions.empty()) {
+ std::vector<std::string> nmeaArraystr;
+ loc_nmea_generate_sv(svNotify, nmeaArraystr);
+ stringstream ss;
+ for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
+ ss << *itor;
+ }
+ string s = ss.str();
+ reportNmea(s.c_str(), s.length());
+ }
+
+ mGnssSvIdUsedInPosAvail = false;
+ mGnssMbSvIdUsedInPosAvail = false;
+}
+
+void
+GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
+{
+ if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
+ !loc_nmea_is_debug(nmea, length)) {
+ return;
+ }
+
+ struct MsgReportNmea : public LocMsg {
+ GnssAdapter& mAdapter;
+ const char* mNmea;
+ size_t mLength;
+ inline MsgReportNmea(GnssAdapter& adapter,
+ const char* nmea,
+ size_t length) :
+ LocMsg(),
+ mAdapter(adapter),
+ mNmea(new char[length+1]),
+ mLength(length) {
+ if (mNmea == nullptr) {
+ LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+ return;
+ }
+ strlcpy((char*)mNmea, nmea, length+1);
+ }
+ inline virtual ~MsgReportNmea()
+ {
+ delete[] mNmea;
+ }
+ inline virtual void proc() const {
+ // extract bug report info - this returns true if consumed by systemstatus
+ bool ret = false;
+ SystemStatus* s = mAdapter.getSystemStatus();
+ if (nullptr != s) {
+ ret = s->setNmeaString(mNmea, mLength);
+ }
+ if (false == ret) {
+ // forward NMEA message to upper layer
+ mAdapter.reportNmea(mNmea, mLength);
+ // DgnssNtrip
+ mAdapter.reportGGAToNtrip(mNmea);
+ }
+ }
+ };
+
+ sendMsg(new MsgReportNmea(*this, nmea, length));
+}
+
+void
+GnssAdapter::reportNmea(const char* nmea, size_t length)
+{
+ GnssNmeaNotification nmeaNotification = {};
+ nmeaNotification.size = sizeof(GnssNmeaNotification);
+
+ struct timeval tv;
+ gettimeofday(&tv, (struct timezone *) NULL);
+ int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
+ nmeaNotification.timestamp = now;
+ nmeaNotification.nmea = nmea;
+ nmeaNotification.length = length;
+
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.gnssNmeaCb) {
+ it->second.gnssNmeaCb(nmeaNotification);
+ }
+ }
+
+ if (isNMEAPrintEnabled()) {
+ LOC_LOGd("[%" PRId64 ", %zu] %s", now, length, nmea);
+ }
+}
+
+void
+GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
+ int msInWeek)
+{
+ struct MsgReportData : public LocMsg {
+ GnssAdapter& mAdapter;
+ GnssDataNotification mDataNotify;
+ int mMsInWeek;
+ inline MsgReportData(GnssAdapter& adapter,
+ const GnssDataNotification& dataNotify,
+ int msInWeek) :
+ LocMsg(),
+ mAdapter(adapter),
+ mDataNotify(dataNotify),
+ mMsInWeek(msInWeek) {
+ }
+ inline virtual void proc() const {
+ if (mMsInWeek >= 0) {
+ mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
+ mMsInWeek);
+ }
+ mAdapter.reportData((GnssDataNotification&)mDataNotify);
+ }
+ };
+
+ sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
+}
+
+void
+GnssAdapter::reportData(GnssDataNotification& dataNotify)
+{
+ for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
+ if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
+ (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
+ LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
+ }
+ if (GNSS_LOC_DATA_AGC_BIT ==
+ (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
+ LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
+ }
+ }
+ for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.gnssDataCb) {
+ it->second.gnssDataCb(dataNotify);
+ }
+ }
+}
+
+bool
+GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data,
+ const LocInEmergency emergencyState)
+{
+ LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
+ "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
+ __func__, notify.type, notify.timeout, notify.timeoutResponse,
+ notify.requestor, notify.requestorEncoding,
+ notify.message, notify.messageEncoding, notify.extras);
+
+ struct MsgReportNiNotify : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ const GnssNiNotification mNotify;
+ const void* mData;
+ const LocInEmergency mEmergencyState;
+ inline MsgReportNiNotify(GnssAdapter& adapter,
+ LocApiBase& api,
+ const GnssNiNotification& notify,
+ const void* data,
+ const LocInEmergency emergencyState) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mNotify(notify),
+ mData(data),
+ mEmergencyState(emergencyState) {}
+ inline virtual void proc() const {
+ bool bIsInEmergency = false;
+ bool bInformNiAccept = false;
+
+ bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
+ mAdapter.getE911State()) || // older modems
+ (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
+
+ if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) &&
+ (GNSS_NI_TYPE_SUPL == mNotify.type || GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type)
+ && !bIsInEmergency &&
+ !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) &&
+ (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) &&
+ 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) {
+ /* If all these conditions are TRUE, then deny the NI Request:
+ -'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked
+ -NI SUPL Request type or NI SUPL Emergency Request type
+ -NOT in an Emergency Call Session
+ -NOT Privacy Override option
+ -NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1 */
+ mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
+ } else if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
+ bInformNiAccept = bIsInEmergency ||
+ (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
+
+ if (bInformNiAccept) {
+ mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
+ } else {
+ mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
+ }
+ } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
+ if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
+ mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
+ }
+ else {
+ mAdapter.requestNiNotify(mNotify, mData, false);
+ }
+ } else {
+ mAdapter.requestNiNotify(mNotify, mData, false);
+ }
+ }
+ };
+
+ sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
+
+ return true;
+}
+
+void
+GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
+
+ // send system info to engine hub
+ mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
+
+ struct MsgLocationSystemInfo : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocationSystemInfo mSystemInfo;
+ inline MsgLocationSystemInfo(GnssAdapter& adapter,
+ const LocationSystemInfo& systemInfo) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSystemInfo(systemInfo) {}
+ inline virtual void proc() const {
+ mAdapter.reportLocationSystemInfo(mSystemInfo);
+ }
+ };
+
+ sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
+}
+
+void
+GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
+ // save the info into the master copy piece by piece, as other system info
+ // may come at different time
+ if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
+ mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
+
+ const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
+ LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
+ if (srcLeapSecondSysInfo.leapSecondInfoMask &
+ LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
+ dstLeapSecondSysInfo.leapSecondInfoMask |=
+ LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
+ dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
+ }
+ // once leap second change event is complete, modem may send up event invalidate the leap
+ // second change info while AP is still processing report during leap second transition
+ // so, we choose to keep this info around even though it is old
+ if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
+ dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
+ dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
+ }
+ }
+
+ // we received new info, inform client of the newly received info
+ if (locationSystemInfo.systemInfoMask) {
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (it->second.locationSystemInfoCb != nullptr) {
+ it->second.locationSystemInfoCb(locationSystemInfo);
+ }
+ }
+ }
+}
+
+static void* niThreadProc(void *args)
+{
+ NiSession* pSession = (NiSession*)args;
+ int rc = 0; /* return code from pthread calls */
+
+ struct timespec present_time;
+ struct timespec expire_time;
+
+ pthread_mutex_lock(&pSession->tLock);
+ /* Calculate absolute expire time */
+ clock_gettime(CLOCK_MONOTONIC, &present_time);
+ expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
+ expire_time.tv_nsec = present_time.tv_nsec;
+ LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
+ __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
+
+ while (!pSession->respRecvd) {
+ rc = pthread_cond_timedwait(&pSession->tCond,
+ &pSession->tLock,
+ &expire_time);
+ if (rc == ETIMEDOUT) {
+ pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
+ LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
+ __func__, rc);
+ break;
+ }
+ }
+ LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
+ "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
+ pSession->respRecvd = false; /* Reset the user response flag for the next session*/
+
+ // adding this check to support modem restart, in which case, we need the thread
+ // to exit without calling sending data. We made sure that rawRequest is NULL in
+ // loc_eng_ni_reset_on_engine_restart()
+ GnssAdapter* adapter = pSession->adapter;
+ GnssNiResponse resp;
+ void* rawRequest = NULL;
+ bool sendResponse = false;
+
+ if (NULL != pSession->rawRequest) {
+ if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
+ resp = pSession->resp;
+ rawRequest = pSession->rawRequest;
+ sendResponse = true;
+ } else {
+ free(pSession->rawRequest);
+ }
+ pSession->rawRequest = NULL;
+ }
+ pthread_mutex_unlock(&pSession->tLock);
+
+ pSession->respTimeLeft = 0;
+ pSession->reqID = 0;
+
+ if (sendResponse) {
+ adapter->gnssNiResponseCommand(resp, rawRequest);
+ }
+
+ return NULL;
+}
+
+bool
+GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
+ const bool bInformNiAccept)
+{
+ NiSession* pSession = NULL;
+ gnssNiCallback gnssNiCb = nullptr;
+
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.gnssNiCb) {
+ gnssNiCb = it->second.gnssNiCb;
+ break;
+ }
+ }
+ if (nullptr == gnssNiCb) {
+ if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
+ if (bInformNiAccept) {
+ mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
+ NiData& niData = getNiData();
+ // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
+ if (NULL != niData.session.rawRequest) {
+ pthread_mutex_lock(&niData.session.tLock);
+ niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
+ niData.session.respRecvd = true;
+ pthread_cond_signal(&niData.session.tCond);
+ pthread_mutex_unlock(&niData.session.tLock);
+ }
+ }
+ }
+ EXIT_LOG(%s, "no clients with gnssNiCb.");
+ return false;
+ }
+
+ if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
+ if (NULL != mNiData.sessionEs.rawRequest) {
+ LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
+ __func__, notify.type);
+ if (NULL != data) {
+ free((void*)data);
+ }
+ } else {
+ pSession = &mNiData.sessionEs;
+ }
+ } else {
+ if (NULL != mNiData.session.rawRequest ||
+ NULL != mNiData.sessionEs.rawRequest) {
+ LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
+ __func__, notify.type);
+ if (NULL != data) {
+ free((void*)data);
+ }
+ } else {
+ pSession = &mNiData.session;
+ }
+ }
+
+ if (pSession) {
+ /* Save request */
+ pSession->rawRequest = (void*)data;
+ pSession->reqID = ++mNiData.reqIDCounter;
+ pSession->adapter = this;
+
+ int sessionId = pSession->reqID;
+
+ /* For robustness, spawn a thread at this point to timeout to clear up the notification
+ * status, even though the OEM layer in java does not do so.
+ **/
+ pSession->respTimeLeft =
+ 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
+
+ int rc = 0;
+ rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
+ if (rc) {
+ LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
+ }
+ rc = pthread_detach(pSession->thread);
+ if (rc) {
+ LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
+ }
+
+ if (nullptr != gnssNiCb) {
+ gnssNiCb(sessionId, notify);
+ }
+ }
+
+ return true;
+}
+
+void
+GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
+ int msInWeek)
+{
+ LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
+
+ if (0 != gnssMeasurements.gnssMeasNotification.count) {
+ struct MsgReportGnssMeasurementData : public LocMsg {
+ GnssAdapter& mAdapter;
+ GnssMeasurements mGnssMeasurements;
+ GnssMeasurementsNotification mMeasurementsNotify;
+ inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
+ const GnssMeasurements& gnssMeasurements,
+ int msInWeek) :
+ LocMsg(),
+ mAdapter(adapter),
+ mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
+ if (-1 != msInWeek) {
+ mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
+ }
+ }
+ inline virtual void proc() const {
+ mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
+ }
+ };
+
+ sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
+ }
+ mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
+ if (mDGnssNeedReport) {
+ reportDGnssDataUsable(gnssMeasurements.gnssSvMeasurementSet);
+ }
+}
+
+void
+GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
+{
+ for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
+ if (nullptr != it->second.gnssMeasurementsCb) {
+ it->second.gnssMeasurementsCb(measurements);
+ }
+ }
+}
+
+void
+GnssAdapter::reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet)
+{
+ uint32_t i;
+ bool preDGnssDataUsage = mDGnssDataUsage;
+
+ mDGnssDataUsage = false;
+ for (i = 0; i < svMeasurementSet.svMeasCount; i++) {
+ const Gnss_SVMeasurementStructType& svMeas = svMeasurementSet.svMeas[i];
+ if (svMeas.dgnssSvMeas.dgnssMeasStatus) {
+ mDGnssDataUsage = true;
+ break;
+ }
+ }
+ if (mDGnssDataUsage != preDGnssDataUsage) {
+ if (mCdfwInterface) {
+ mCdfwInterface->reportUsable(mQDgnssListenerHDL, mDGnssDataUsage);
+ }
+ }
+}
+
+void
+GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
+{
+ LOC_LOGD("%s]: ", __func__);
+ mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
+}
+
+void
+GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
+{
+ LOC_LOGD("%s]:", __func__);
+ mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
+}
+
+
+bool
+GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
+{
+ struct MsgRequestOdcpi : public LocMsg {
+ GnssAdapter& mAdapter;
+ OdcpiRequestInfo mOdcpiRequest;
+ inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
+ LocMsg(),
+ mAdapter(adapter),
+ mOdcpiRequest(request) {}
+ inline virtual void proc() const {
+ mAdapter.requestOdcpi(mOdcpiRequest);
+ }
+ };
+
+ sendMsg(new MsgRequestOdcpi(*this, request));
+ return true;
+}
+
+void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
+{
+ if (nullptr != mOdcpiRequestCb) {
+ LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
+ " requestActive: %d timerActive: %d",
+ request.type, request.tbfMillis, request.isEmergencyMode,
+ mOdcpiRequestActive, mOdcpiTimer.isActive());
+ // ODCPI START and ODCPI STOP from modem can come in quick succession
+ // so the mOdcpiTimer helps avoid spamming the framework as well as
+ // extending the odcpi session past 30 seconds if needed
+ if (ODCPI_REQUEST_TYPE_START == request.type) {
+ if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
+ mOdcpiRequestCb(request);
+ mOdcpiRequestActive = true;
+ mOdcpiTimer.start();
+ // if the current active odcpi session is non-emergency, and the new
+ // odcpi request is emergency, replace the odcpi request with new request
+ // and restart the timer
+ } else if (false == mOdcpiRequest.isEmergencyMode &&
+ true == request.isEmergencyMode) {
+ mOdcpiRequestCb(request);
+ mOdcpiRequestActive = true;
+ if (true == mOdcpiTimer.isActive()) {
+ mOdcpiTimer.restart();
+ } else {
+ mOdcpiTimer.start();
+ }
+ // if ODCPI request is not active but the timer is active, then
+ // just update the active state and wait for timer to expire
+ // before requesting new ODCPI to avoid spamming ODCPI requests
+ } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
+ mOdcpiRequestActive = true;
+ }
+ mOdcpiRequest = request;
+ // the request is being stopped, but allow timer to expire first
+ // before stopping the timer just in case more ODCPI requests come
+ // to avoid spamming more odcpi requests to the framework
+ } else if (ODCPI_REQUEST_TYPE_STOP == request.type) {
+ LOC_LOGd("request: type %d, isEmergency %d", request.type, request.isEmergencyMode);
+ mOdcpiRequestCb(request);
+ mOdcpiRequestActive = false;
+ } else {
+ LOC_LOGE("Invalid ODCPI request type..");
+ }
+ } else {
+ LOC_LOGw("ODCPI request not supported");
+ }
+}
+
+bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
+{
+ LOC_LOGD("%s]:", __func__);
+ mEngHubProxy->gnssDeleteAidingData(aidingData);
+ return true;
+}
+
+bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
+{
+ LOC_LOGD("%s]:", __func__);
+ mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
+ return true;
+}
+
+bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
+ GnssAdditionalSystemInfo & additionalSystemInfo)
+{
+ LOC_LOGD("%s]:", __func__);
+ mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
+ return true;
+}
+
+bool GnssAdapter::reportQwesCapabilities(
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
+{
+ struct MsgReportQwesFeatureStatus : public LocMsg {
+ GnssAdapter& mAdapter;
+ const std::unordered_map<LocationQwesFeatureType, bool> mFeatureMap;
+ inline MsgReportQwesFeatureStatus(GnssAdapter& adapter,
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) :
+ LocMsg(),
+ mAdapter(adapter),
+ mFeatureMap(std::move(featureMap)) {}
+ inline virtual void proc() const {
+ LOC_LOGi("ReportQwesFeatureStatus before caps %" PRIx64 " ",
+ mAdapter.getCapabilities());
+ ContextBase::setQwesFeatureStatus(mFeatureMap);
+ LOC_LOGi("ReportQwesFeatureStatus After caps %" PRIx64 " ",
+ mAdapter.getCapabilities());
+ mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
+ }
+ };
+
+ sendMsg(new MsgReportQwesFeatureStatus(*this, featureMap));
+ return true;
+}
+
+void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback,
+ OdcpiPrioritytype priority)
+{
+ struct MsgInitOdcpi : public LocMsg {
+ GnssAdapter& mAdapter;
+ OdcpiRequestCallback mOdcpiCb;
+ OdcpiPrioritytype mPriority;
+ inline MsgInitOdcpi(GnssAdapter& adapter,
+ const OdcpiRequestCallback& callback,
+ OdcpiPrioritytype priority) :
+ LocMsg(),
+ mAdapter(adapter),
+ mOdcpiCb(callback), mPriority(priority){}
+ inline virtual void proc() const {
+ mAdapter.initOdcpi(mOdcpiCb, mPriority);
+ }
+ };
+
+ sendMsg(new MsgInitOdcpi(*this, callback, priority));
+}
+
+void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback,
+ OdcpiPrioritytype priority)
+{
+ LOC_LOGd("In priority: %d, Curr priority: %d", priority, mCallbackPriority);
+ if (priority >= mCallbackPriority) {
+ mOdcpiRequestCb = callback;
+ mCallbackPriority = priority;
+ /* Register for WIFI request */
+ updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
+ LOC_REGISTRATION_MASK_ENABLED);
+ }
+}
+
+void GnssAdapter::injectOdcpiCommand(const Location& location)
+{
+ struct MsgInjectOdcpi : public LocMsg {
+ GnssAdapter& mAdapter;
+ Location mLocation;
+ inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
+ LocMsg(),
+ mAdapter(adapter),
+ mLocation(location) {}
+ inline virtual void proc() const {
+ mAdapter.injectOdcpi(mLocation);
+ }
+ };
+
+ sendMsg(new MsgInjectOdcpi(*this, location));
+}
+
+void GnssAdapter::injectOdcpi(const Location& location)
+{
+ LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
+ "lat %.7f long %.7f",
+ mOdcpiRequestActive, mOdcpiTimer.isActive(),
+ location.latitude, location.longitude);
+
+ mLocApi->injectPosition(location, true);
+}
+
+// Called in the context of LocTimer thread
+void OdcpiTimer::timeOutCallback()
+{
+ if (nullptr != mAdapter) {
+ mAdapter->odcpiTimerExpireEvent();
+ }
+}
+
+// Called in the context of LocTimer thread
+void GnssAdapter::odcpiTimerExpireEvent()
+{
+ struct MsgOdcpiTimerExpire : public LocMsg {
+ GnssAdapter& mAdapter;
+ inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ inline virtual void proc() const {
+ mAdapter.odcpiTimerExpire();
+ }
+ };
+ sendMsg(new MsgOdcpiTimerExpire(*this));
+}
+void GnssAdapter::odcpiTimerExpire()
+{
+ LOC_LOGd("requestActive: %d timerActive: %d",
+ mOdcpiRequestActive, mOdcpiTimer.isActive());
+
+ // if ODCPI request is still active after timer
+ // expires, request again and restart timer
+ if (mOdcpiRequestActive) {
+ mOdcpiRequestCb(mOdcpiRequest);
+ mOdcpiTimer.restart();
+ } else {
+ mOdcpiTimer.stop();
+ }
+}
+
+void
+GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
+ if (mGnssEnergyConsumedCb) {
+ mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
+ mGnssEnergyConsumedCb = nullptr;
+ }
+}
+
+bool
+GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
+ LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
+
+ struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint64_t mGnssEnergyConsumedSinceFirstBoot;
+ inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
+ uint64_t energyConsumed) :
+ LocMsg(),
+ mAdapter(adapter),
+ mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
+ inline virtual void proc() const {
+ mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
+ }
+ };
+
+ sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
+ return true;
+}
+
+void GnssAdapter::initDefaultAgps() {
+ LOC_LOGD("%s]: ", __func__);
+ void *handle = nullptr;
+
+ LocAgpsGetAgpsCbInfo getAgpsCbInfo =
+ (LocAgpsGetAgpsCbInfo)dlGetSymFromLib(handle, "libloc_net_iface.so",
+ "LocNetIfaceAgps_getAgpsCbInfo");
+ // Below step is to make sure we init nativeAgpsHandler
+ // for Android platforms only
+ AgpsCbInfo cbInfo = {};
+ if (nullptr != getAgpsCbInfo) {
+ cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
+ } else {
+ cbInfo = mNativeAgpsHandler.getAgpsCbInfo();
+ }
+
+ if (cbInfo.statusV4Cb == nullptr) {
+ LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
+ dlclose(handle);
+ return;
+ }
+
+ initAgps(cbInfo);
+}
+
+void GnssAdapter::initDefaultAgpsCommand() {
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgInitDefaultAgps : public LocMsg {
+ GnssAdapter& mAdapter;
+ inline MsgInitDefaultAgps(GnssAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {
+ }
+ inline virtual void proc() const {
+ mAdapter.initDefaultAgps();
+ }
+ };
+
+ sendMsg(new MsgInitDefaultAgps(*this));
+}
+
+/* INIT LOC AGPS MANAGER */
+
+void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
+ LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
+
+ if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
+ (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
+ return;
+ }
+
+ mAgpsManager.createAgpsStateMachines(cbInfo);
+ /* Register for AGPS event mask */
+ updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
+ LOC_REGISTRATION_MASK_ENABLED);
+}
+
+void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
+ LOC_LOGI("GnssAdapter::initAgpsCommand");
+
+ /* Message to initialize AGPS module */
+ struct AgpsMsgInit: public LocMsg {
+ const AgpsCbInfo mCbInfo;
+ GnssAdapter& mAdapter;
+
+ inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
+ GnssAdapter& adapter) :
+ LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
+ LOC_LOGV("AgpsMsgInit");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGV("AgpsMsgInit::proc()");
+ mAdapter.initAgps(mCbInfo);
+ }
+ };
+
+ /* Send message to initialize AGPS Manager */
+ sendMsg(new AgpsMsgInit(cbInfo, *this));
+}
+
+void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
+ LOC_LOGi("GnssAdapter::initNfwCommand");
+
+ /* Message to initialize NFW */
+ struct MsgInitNfw : public LocMsg {
+ const NfwCbInfo mCbInfo;
+ GnssAdapter& mAdapter;
+
+ inline MsgInitNfw(const NfwCbInfo& cbInfo,
+ GnssAdapter& adapter) :
+ LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
+ LOC_LOGv("MsgInitNfw");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGv("MsgInitNfw::proc()");
+ mAdapter.initNfw(mCbInfo);
+ }
+ };
+
+ /* Send message to initialize NFW */
+ sendMsg(new MsgInitNfw(cbInfo, *this));
+}
+
+void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
+ LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
+
+ struct MsgReportNfwNotification : public LocMsg {
+ const GnssNfwNotification mNotification;
+ GnssAdapter& mAdapter;
+
+ inline MsgReportNfwNotification(const GnssNfwNotification& notification,
+ GnssAdapter& adapter) :
+ LocMsg(), mNotification(notification), mAdapter(adapter) {
+ LOC_LOGv("MsgReportNfwNotification");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGv("MsgReportNfwNotification::proc()");
+ mAdapter.reportNfwNotification(mNotification);
+ }
+ };
+
+ sendMsg(new MsgReportNfwNotification(notification, *this));
+}
+
+/* GnssAdapter::requestATL
+ * Method triggered in QMI thread as part of handling below message:
+ * eQMI_LOC_SERVER_REQUEST_OPEN_V02
+ * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
+ * eQMI_LOC_WWAN_TYPE_INTERNET_V02
+ * eQMI_LOC_WWAN_TYPE_AGNSS_V02
+ * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
+bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
+ LocApnTypeMask apnTypeMask){
+
+ LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
+ connHandle, agpsType, apnTypeMask);
+
+ sendMsg( new AgpsMsgRequestATL(
+ &mAgpsManager, connHandle, (AGpsExtType)agpsType,
+ apnTypeMask));
+
+ return true;
+}
+
+/* GnssAdapter::releaseATL
+ * Method triggered in QMI thread as part of handling below message:
+ * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
+ * Triggers teardown of an existing AGPS call */
+bool GnssAdapter::releaseATL(int connHandle){
+
+ LOC_LOGI("GnssAdapter::releaseATL");
+
+ /* Release SUPL/INTERNET/SUPL_ES ATL */
+ struct AgpsMsgReleaseATL: public LocMsg {
+
+ AgpsManager* mAgpsManager;
+ int mConnHandle;
+
+ inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
+ LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
+
+ LOC_LOGV("AgpsMsgReleaseATL");
+ }
+
+ inline virtual void proc() const {
+
+ LOC_LOGV("AgpsMsgReleaseATL::proc()");
+ mAgpsManager->releaseATL(mConnHandle);
+ }
+ };
+
+ sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
+
+ return true;
+}
+
+void GnssAdapter::dataConnOpenCommand(
+ AGpsExtType agpsType,
+ const char* apnName, int apnLen, AGpsBearerType bearerType){
+
+ LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
+
+ struct AgpsMsgAtlOpenSuccess: public LocMsg {
+
+ AgpsManager* mAgpsManager;
+ AGpsExtType mAgpsType;
+ char* mApnName;
+ int mApnLen;
+ AGpsBearerType mBearerType;
+
+ inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
+ const char* apnName, int apnLen, AGpsBearerType bearerType) :
+ LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
+ new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
+
+ LOC_LOGV("AgpsMsgAtlOpenSuccess");
+ if (mApnName == nullptr) {
+ LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
+ // Reporting the failure here
+ mAgpsManager->reportAtlClosed(mAgpsType);
+ return;
+ }
+ memcpy(mApnName, apnName, apnLen);
+ mApnName[apnLen] = 0;
+ }
+
+ inline ~AgpsMsgAtlOpenSuccess() {
+ delete[] mApnName;
+ }
+
+ inline virtual void proc() const {
+
+ LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
+ mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
+ }
+ };
+ // Added inital length checks for apnlen check to avoid security issues
+ // In case of failure reporting the same
+ if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN ||
+ (strlen(apnName) != (unsigned)apnLen)) {
+ LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
+ mAgpsManager.reportAtlClosed(agpsType);
+ } else {
+ sendMsg( new AgpsMsgAtlOpenSuccess(
+ &mAgpsManager, agpsType, apnName, apnLen, bearerType));
+ }
+}
+
+void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
+
+ LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
+
+ struct AgpsMsgAtlClosed: public LocMsg {
+
+ AgpsManager* mAgpsManager;
+ AGpsExtType mAgpsType;
+
+ inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
+ LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
+
+ LOC_LOGV("AgpsMsgAtlClosed");
+ }
+
+ inline virtual void proc() const {
+
+ LOC_LOGV("AgpsMsgAtlClosed::proc()");
+ mAgpsManager->reportAtlClosed(mAgpsType);
+ }
+ };
+
+ sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
+}
+
+void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
+
+ LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
+
+ struct AgpsMsgAtlOpenFailed: public LocMsg {
+
+ AgpsManager* mAgpsManager;
+ AGpsExtType mAgpsType;
+
+ inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
+ LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
+
+ LOC_LOGV("AgpsMsgAtlOpenFailed");
+ }
+
+ inline virtual void proc() const {
+
+ LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
+ mAgpsManager->reportAtlOpenFailed(mAgpsType);
+ }
+ };
+
+ sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
+}
+
+void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
+ const GnssSvType& in_constellation,
+ const SystemStatusReports& in)
+{
+ uint64_t sv_mask = 0ULL;
+ uint32_t svid_min = 0;
+ uint32_t svid_num = 0;
+ uint32_t svid_idx = 0;
+
+ uint64_t eph_health_good_mask = 0ULL;
+ uint64_t eph_health_bad_mask = 0ULL;
+ uint64_t server_perdiction_available_mask = 0ULL;
+ float server_perdiction_age = 0.0f;
+
+ // set constellationi based parameters
+ switch (in_constellation) {
+ case GNSS_SV_TYPE_GPS:
+ svid_min = GNSS_BUGREPORT_GPS_MIN;
+ svid_num = GPS_NUM;
+ svid_idx = 0;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
+ }
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ svid_min = GNSS_BUGREPORT_GLO_MIN;
+ svid_num = GLO_NUM;
+ svid_idx = GPS_NUM;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ svid_min = GNSS_BUGREPORT_QZSS_MIN;
+ svid_num = QZSS_NUM;
+ svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
+ }
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ svid_min = GNSS_BUGREPORT_BDS_MIN;
+ svid_num = BDS_NUM;
+ svid_idx = GPS_NUM+GLO_NUM;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
+ }
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ svid_min = GNSS_BUGREPORT_GAL_MIN;
+ svid_num = GAL_NUM;
+ svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
+ }
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ svid_min = GNSS_BUGREPORT_NAVIC_MIN;
+ svid_num = NAVIC_NUM;
+ svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
+ if (!in.mSvHealth.empty()) {
+ eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
+ eph_health_bad_mask = in.mSvHealth.back().mNavicBadMask;
+ }
+ if (!in.mXtra.empty()) {
+ server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
+ server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
+ }
+ break;
+ default:
+ return;
+ }
+
+ // extract each sv info from systemstatus report
+ for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
+
+ GnssDebugSatelliteInfo s = {};
+ s.size = sizeof(s);
+ s.svid = i + svid_min;
+ s.constellation = in_constellation;
+
+ if (!in.mNavData.empty()) {
+ s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
+ s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
+ }
+ else {
+ s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
+ s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
+ }
+
+ sv_mask = 0x1ULL << i;
+ if (eph_health_good_mask & sv_mask) {
+ s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
+ }
+ else if (eph_health_bad_mask & sv_mask) {
+ s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
+ }
+ else {
+ s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
+ }
+
+ if (!in.mNavData.empty()) {
+ s.ephemerisAgeSeconds =
+ (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
+ }
+ else {
+ s.ephemerisAgeSeconds = 0.0f;
+ }
+
+ if (server_perdiction_available_mask & sv_mask) {
+ s.serverPredictionIsAvailable = true;
+ }
+ else {
+ s.serverPredictionIsAvailable = false;
+ }
+
+ s.serverPredictionAgeSeconds = server_perdiction_age;
+ out.push_back(s);
+ }
+
+ return;
+}
+
+bool GnssAdapter::getDebugReport(GnssDebugReport& r)
+{
+ LOC_LOGD("%s]: ", __func__);
+
+ SystemStatus* systemstatus = getSystemStatus();
+ if (nullptr == systemstatus) {
+ return false;
+ }
+
+ SystemStatusReports reports = {};
+ systemstatus->getReport(reports, true);
+
+ r.size = sizeof(r);
+
+ // location block
+ r.mLocation.size = sizeof(r.mLocation);
+ if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
+ r.mLocation.mValid = true;
+ r.mLocation.mLocation.latitude =
+ reports.mLocation.back().mLocation.gpsLocation.latitude;
+ r.mLocation.mLocation.longitude =
+ reports.mLocation.back().mLocation.gpsLocation.longitude;
+ r.mLocation.mLocation.altitude =
+ reports.mLocation.back().mLocation.gpsLocation.altitude;
+ r.mLocation.mLocation.speed =
+ (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
+ r.mLocation.mLocation.bearing =
+ (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
+ r.mLocation.mLocation.accuracy =
+ (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
+
+ r.mLocation.verticalAccuracyMeters =
+ reports.mLocation.back().mLocationEx.vert_unc;
+ r.mLocation.speedAccuracyMetersPerSecond =
+ reports.mLocation.back().mLocationEx.speed_unc;
+ r.mLocation.bearingAccuracyDegrees =
+ reports.mLocation.back().mLocationEx.bearing_unc;
+
+ r.mLocation.mUtcReported =
+ reports.mLocation.back().mUtcReported;
+ }
+ else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
+ r.mLocation.mValid = true;
+ r.mLocation.mLocation.latitude =
+ (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
+ r.mLocation.mLocation.longitude =
+ (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
+ r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
+ r.mLocation.mLocation.accuracy =
+ (double)(reports.mBestPosition.back().mBestHepe);
+
+ r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
+ }
+ else {
+ r.mLocation.mValid = false;
+ }
+
+ if (r.mLocation.mValid) {
+ LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
+ r.mLocation.mLocation.latitude,
+ r.mLocation.mLocation.longitude,
+ r.mLocation.mLocation.altitude,
+ r.mLocation.mLocation.speed);
+ }
+
+ // time block
+ r.mTime.size = sizeof(r.mTime);
+ if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
+ r.mTime.mValid = true;
+ r.mTime.timeEstimate =
+ (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
+ GNSS_UTC_TIME_OFFSET)*24*60*60 -
+ (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
+ (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
+
+ if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
+ // TimeUncNs value is available
+ r.mTime.timeUncertaintyNs =
+ (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
+ (float)(reports.mTimeAndClock.back().mTimeUncNs);
+ } else {
+ // fall back to legacy TimeUnc
+ r.mTime.timeUncertaintyNs =
+ ((float)(reports.mTimeAndClock.back().mTimeUnc) +
+ (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
+ }
+
+ r.mTime.frequencyUncertaintyNsPerSec =
+ (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
+ LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
+ r.mTime.timeEstimate,
+ r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
+ }
+ else {
+ r.mTime.mValid = false;
+ }
+
+ // satellite info block
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
+ convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
+ LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
+
+ return true;
+}
+
+/* get AGC information from system status and fill it */
+void
+GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
+{
+ SystemStatus* systemstatus = getSystemStatus();
+
+ if (nullptr != systemstatus) {
+ SystemStatusReports reports = {};
+ systemstatus->getReport(reports, true);
+
+ if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
+ (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
+
+ for (size_t i = 0; i < measurements.count; i++) {
+ switch (measurements.measurements[i].svType) {
+ case GNSS_SV_TYPE_GPS:
+ case GNSS_SV_TYPE_QZSS:
+ measurements.measurements[i].agcLevelDb =
+ reports.mRfAndParams.back().mAgcGps;
+ measurements.measurements[i].flags |=
+ GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
+ break;
+
+ case GNSS_SV_TYPE_GALILEO:
+ measurements.measurements[i].agcLevelDb =
+ reports.mRfAndParams.back().mAgcGal;
+ measurements.measurements[i].flags |=
+ GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
+ break;
+
+ case GNSS_SV_TYPE_GLONASS:
+ measurements.measurements[i].agcLevelDb =
+ reports.mRfAndParams.back().mAgcGlo;
+ measurements.measurements[i].flags |=
+ GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
+ break;
+
+ case GNSS_SV_TYPE_BEIDOU:
+ measurements.measurements[i].agcLevelDb =
+ reports.mRfAndParams.back().mAgcBds;
+ measurements.measurements[i].flags |=
+ GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
+ break;
+
+ case GNSS_SV_TYPE_SBAS:
+ case GNSS_SV_TYPE_UNKNOWN:
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* get Data information from system status and fill it */
+void
+GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
+{
+ SystemStatus* systemstatus = getSystemStatus();
+
+ LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
+ if (nullptr != systemstatus) {
+ SystemStatusReports reports = {};
+ systemstatus->getReport(reports, true);
+
+ if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
+ (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
+
+ for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
+ sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
+ data.gnssDataMask[sig] = 0;
+ data.jammerInd[sig] = 0.0;
+ data.agc[sig] = 0.0;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGps) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
+ reports.mRfAndParams.back().mAgcGps;
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
+ reports.mRfAndParams.back().mAgcGps;
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
+ reports.mRfAndParams.back().mAgcGps;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
+ (double)reports.mRfAndParams.back().mJammerGps;
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
+ (double)reports.mRfAndParams.back().mJammerGps;
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
+ (double)reports.mRfAndParams.back().mJammerGps;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGlo) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
+ reports.mRfAndParams.back().mAgcGlo;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
+ (double)reports.mRfAndParams.back().mJammerGlo;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcBds) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
+ reports.mRfAndParams.back().mAgcBds;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
+ (double)reports.mRfAndParams.back().mJammerBds;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGal) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
+ GNSS_LOC_DATA_AGC_BIT;
+ data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
+ reports.mRfAndParams.back().mAgcGal;
+ }
+ if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
+ data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
+ GNSS_LOC_DATA_JAMMER_IND_BIT;
+ data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
+ (double)reports.mRfAndParams.back().mJammerGal;
+ }
+ }
+ }
+}
+
+/* Callbacks registered with loc_net_iface library */
+static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
+ AGpsBearerType bearerType, void* userDataPtr) {
+ LOC_LOGD("%s]: ", __func__);
+ if (userDataPtr == nullptr) {
+ LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
+ return;
+ }
+ if (apn == nullptr) {
+ LOC_LOGE("%s]: apn is nullptr.", __func__);
+ return;
+ }
+ GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
+ if (isSuccess) {
+ adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
+ } else {
+ adapter->dataConnFailedCommand(agpsType);
+ }
+}
+
+static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
+ LOC_LOGD("%s]: ", __func__);
+ if (userDataPtr == nullptr) {
+ LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
+ return;
+ }
+ GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
+ if (isSuccess) {
+ adapter->dataConnClosedCommand(agpsType);
+ } else {
+ adapter->dataConnFailedCommand(agpsType);
+ }
+}
+
+void
+GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
+ mGnssEnergyConsumedCb = energyConsumedCb;
+}
+
+void
+GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
+ struct MsgGetGnssEnergyConsumed : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ GnssEnergyConsumedCallback mEnergyConsumedCb;
+ inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
+ GnssEnergyConsumedCallback energyConsumedCb) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mEnergyConsumedCb(energyConsumedCb){}
+ inline virtual void proc() const {
+ mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
+ mApi.getGnssEnergyConsumed();
+ }
+ };
+
+ sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
+}
+
+void
+GnssAdapter::nfwControlCommand(bool enable) {
+ struct MsgControlNfwLocationAccess : public LocMsg {
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+ bool mEnable;
+ inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
+ bool enable) :
+ LocMsg(),
+ mAdapter(adapter),
+ mApi(api),
+ mEnable(enable) {}
+ inline virtual void proc() const {
+ GnssConfigGpsLock gpsLock;
+
+ gpsLock = ContextBase::mGps_conf.GPS_LOCK;
+ if (mEnable) {
+ gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
+ } else {
+ gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
+ }
+ ContextBase::mGps_conf.GPS_LOCK = gpsLock;
+ mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
+ mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
+ }));
+ }
+ };
+
+ if (mSupportNfwControl) {
+ sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
+ } else {
+ LOC_LOGw("NFW control is not supported, do not use this for NFW");
+ }
+}
+
+// Set tunc constrained mode, use 0 session id to indicate
+// that no callback is needed. Session id 0 is used for calls that
+// are not invoked from the integration api, e.g.: initial configuration
+// from the configure file
+void
+GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint,
+ uint32_t energyBudget, uint32_t sessionId) {
+
+ mLocConfigInfo.tuncConfigInfo.isValid = true;
+ mLocConfigInfo.tuncConfigInfo.enable = enable;
+ mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint;
+ mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget;
+
+ LocApiResponse* locApiResponse = nullptr;
+ if (sessionId != 0) {
+ locApiResponse =
+ new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+ }
+ mLocApi->setConstrainedTuncMode(
+ enable, tuncConstraint, energyBudget, locApiResponse);
+}
+
+uint32_t
+GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint,
+ uint32_t energyBudget) {
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgEnableTUNC : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ bool mEnable;
+ float mTuncConstraint;
+ uint32_t mEnergyBudget;
+
+ inline MsgEnableTUNC(GnssAdapter& adapter,
+ uint32_t sessionId,
+ bool enable,
+ float tuncConstraint,
+ uint32_t energyBudget) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mEnable(enable),
+ mTuncConstraint(tuncConstraint),
+ mEnergyBudget(energyBudget) {}
+ inline virtual void proc() const {
+ mAdapter.setConstrainedTunc(mEnable, mTuncConstraint,
+ mEnergyBudget, mSessionId);
+ }
+ };
+
+ sendMsg(new MsgEnableTUNC(*this, sessionId, enable,
+ tuncConstraint, energyBudget));
+
+ return sessionId;
+}
+
+// Set position assisted clock estimator, use 0 session id to indicate
+// that no callback is needed. Session id 0 is used for calls that are
+// not invoked from the integration api, e.g.: initial configuration
+// from the configure file.
+void
+GnssAdapter::setPositionAssistedClockEstimator(bool enable,
+ uint32_t sessionId) {
+
+ mLocConfigInfo.paceConfigInfo.isValid = true;
+ mLocConfigInfo.paceConfigInfo.enable = enable;
+ LocApiResponse* locApiResponse = nullptr;
+ if (sessionId != 0) {
+ locApiResponse =
+ new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+ }
+ mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse);
+}
+
+uint32_t
+GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) {
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgEnablePACE : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ bool mEnable;
+ inline MsgEnablePACE(GnssAdapter& adapter,
+ uint32_t sessionId, bool enable) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mEnable(enable){}
+ inline virtual void proc() const {
+ mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId);
+ }
+ };
+
+ sendMsg(new MsgEnablePACE(*this, sessionId, enable));
+ return sessionId;
+}
+
+void GnssAdapter::gnssUpdateSvConfig(
+ uint32_t sessionId, const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) {
+
+ // suspend all tracking sessions to apply the constellation config
+ suspendSessions();
+ if (constellationEnablementConfig.size == sizeof(constellationEnablementConfig)) {
+ // check whether if any constellation is removed from the new config
+ GnssSvTypesMask currentEnabledMask = mGnssSvTypeConfig.enabledSvTypesMask;
+ GnssSvTypesMask newEnabledMask = constellationEnablementConfig.enabledSvTypesMask;
+ GnssSvTypesMask enabledRemoved = currentEnabledMask & (currentEnabledMask ^ newEnabledMask);
+ // Send reset if any constellation is removed from the enabled list
+ if (enabledRemoved != 0) {
+ mLocApi->resetConstellationControl();
+ }
+
+ // if the constellation config is valid, issue request to modem
+ // to enable/disable constellation
+ mLocApi->setConstellationControl(mGnssSvTypeConfig);
+ } else if (constellationEnablementConfig.size == 0) {
+ // when the size is not set, meaning reset to modem default
+ mLocApi->resetConstellationControl();
+ }
+ // save the constellation settings to be used for modem SSR
+ mGnssSvTypeConfig = constellationEnablementConfig;
+
+ // handle blacklisted SV settings
+ mGnssSvIdConfig = blacklistSvConfig;
+ // process blacklist svs info
+ mBlacklistedSvIds.clear();
+ // need to save the balcklisted sv info into mBlacklistedSvIds as well
+ convertFromGnssSvIdConfig(blacklistSvConfig, mBlacklistedSvIds);
+ LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+ mLocApi->setBlacklistSv(mGnssSvIdConfig, locApiResponse);
+
+ // resume all tracking sessions after the constellation config has been applied
+ restartSessions(false);
+}
+
+uint32_t
+GnssAdapter::gnssUpdateSvConfigCommand(
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgUpdateSvConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ GnssSvTypeConfig mConstellationEnablementConfig;
+ GnssSvIdConfig mBlacklistSvIdConfig;
+
+ inline MsgUpdateSvConfig(GnssAdapter& adapter,
+ uint32_t sessionId,
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mConstellationEnablementConfig(constellationEnablementConfig),
+ mBlacklistSvIdConfig(blacklistSvConfig) {}
+ inline virtual void proc() const {
+ mAdapter.gnssUpdateSvConfig(mSessionId, mConstellationEnablementConfig,
+ mBlacklistSvIdConfig);
+ }
+ };
+
+ if (sessionId != 0) {
+ sendMsg(new MsgUpdateSvConfig(*this, sessionId, constellationEnablementConfig,
+ blacklistSvConfig));
+ }
+ return sessionId;
+}
+
+void GnssAdapter::gnssUpdateSecondaryBandConfig(
+ uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig) {
+
+ LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+
+ // handle secondary band info
+ mGnssSeconaryBandConfig = secondaryBandConfig;
+ gnssSecondaryBandConfigUpdate(locApiResponse);
+}
+
+uint32_t
+GnssAdapter::gnssUpdateSecondaryBandConfigCommand(
+ const GnssSvTypeConfig& secondaryBandConfig) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgUpdateSecondaryBandConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ GnssSvTypeConfig mSecondaryBandConfig;
+
+ inline MsgUpdateSecondaryBandConfig(GnssAdapter& adapter,
+ uint32_t sessionId,
+ const GnssSvTypeConfig& secondaryBandConfig) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mSecondaryBandConfig(secondaryBandConfig) {}
+ inline virtual void proc() const {
+ mAdapter.gnssUpdateSecondaryBandConfig(mSessionId, mSecondaryBandConfig);
+ }
+ };
+
+ if (sessionId != 0) {
+ sendMsg(new MsgUpdateSecondaryBandConfig(*this, sessionId, secondaryBandConfig));
+ }
+ return sessionId;
+}
+
+// This function currently retrieves secondary band configuration
+// for constellation enablement/disablement.
+void
+GnssAdapter::gnssGetSecondaryBandConfig(uint32_t sessionId) {
+
+ LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+
+ mLocApi->getConstellationMultiBandConfig(sessionId, locApiResponse);
+}
+
+uint32_t
+GnssAdapter::gnssGetSecondaryBandConfigCommand() {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgGetSecondaryBandConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ inline MsgGetSecondaryBandConfig(GnssAdapter& adapter,
+ uint32_t sessionId) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId) {}
+ inline virtual void proc() const {
+ mAdapter.gnssGetSecondaryBandConfig(mSessionId);
+ }
+ };
+
+ if (sessionId != 0) {
+ sendMsg(new MsgGetSecondaryBandConfig(*this, sessionId));
+ }
+ return sessionId;
+}
+
+void
+GnssAdapter::configLeverArm(uint32_t sessionId,
+ const LeverArmConfigInfo& configInfo) {
+
+ LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+ if (true == mEngHubProxy->configLeverArm(configInfo)) {
+ err = LOCATION_ERROR_SUCCESS;
+ }
+ reportResponse(err, sessionId);
+}
+
+uint32_t
+GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgConfigLeverArm : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ LeverArmConfigInfo mConfigInfo;
+
+ inline MsgConfigLeverArm(GnssAdapter& adapter,
+ uint32_t sessionId,
+ const LeverArmConfigInfo& configInfo) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mConfigInfo(configInfo) {}
+ inline virtual void proc() const {
+ // save the lever ARM config info for translating position from GNSS antenna based
+ // to VRP based
+ if (mConfigInfo.leverArmValidMask & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT) {
+ mAdapter.mLocConfigInfo.leverArmConfigInfo.leverArmValidMask |=
+ LEVER_ARM_TYPE_GNSS_TO_VRP_BIT;
+ mAdapter.mLocConfigInfo.leverArmConfigInfo.gnssToVRP = mConfigInfo.gnssToVRP;
+ }
+ mAdapter.configLeverArm(mSessionId, mConfigInfo);
+ }
+ };
+
+ sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo));
+ return sessionId;
+}
+
+bool GnssAdapter::initMeasCorr(bool bSendCbWhenNotSupported) {
+ LOC_LOGv("GnssAdapter::initMeasCorr");
+ /* Message to initialize Measurement Corrections */
+ struct MsgInitMeasCorr : public LocMsg {
+ GnssAdapter& mAdapter;
+ GnssMeasurementCorrectionsCapabilitiesMask mCapMask;
+
+ inline MsgInitMeasCorr(GnssAdapter& adapter,
+ GnssMeasurementCorrectionsCapabilitiesMask capMask) :
+ LocMsg(), mAdapter(adapter), mCapMask(capMask) {
+ LOC_LOGv("MsgInitMeasCorr");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGv("MsgInitMeasCorr::proc()");
+
+ mAdapter.mMeasCorrSetCapabilitiesCb(mCapMask);
+ }
+ };
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+ sendMsg(new MsgInitMeasCorr(*this, GNSS_MEAS_CORR_LOS_SATS |
+ GNSS_MEAS_CORR_EXCESS_PATH_LENGTH | GNSS_MEAS_CORR_REFLECTING_PLANE));
+ return true;
+ } else {
+ LOC_LOGv("MEASUREMENTS_CORRECTION feature is not supported in the modem");
+ if (bSendCbWhenNotSupported) {
+ sendMsg(new MsgInitMeasCorr(*this, 0));
+ }
+ return false;
+ }
+}
+
+bool GnssAdapter::openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
+ LOC_LOGi("GnssAdapter::openMeasCorrCommand");
+
+ /* Send message to initialize Measurement Corrections */
+ mMeasCorrSetCapabilitiesCb = setCapabilitiesCb;
+ mIsMeasCorrInterfaceOpen = true;
+ if (isEngineCapabilitiesKnown()) {
+ LOC_LOGv("Capabilities are known, proceed with measurement corrections init");
+ return initMeasCorr(false);
+ } else {
+ LOC_LOGv("Capabilities are not known, wait for open");
+ return true;
+ }
+}
+
+bool GnssAdapter::measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr) {
+ LOC_LOGi("GnssAdapter::measCorrSetCorrectionsCommand");
+
+ /* Message to set Measurement Corrections */
+ struct MsgSetCorrectionsMeasCorr : public LocMsg {
+ const GnssMeasurementCorrections mGnssMeasCorr;
+ GnssAdapter& mAdapter;
+ LocApiBase& mApi;
+
+ inline MsgSetCorrectionsMeasCorr(
+ const GnssMeasurementCorrections gnssMeasCorr,
+ GnssAdapter& adapter,
+ LocApiBase& api) :
+ LocMsg(),
+ mGnssMeasCorr(gnssMeasCorr),
+ mAdapter(adapter),
+ mApi(api) {
+ LOC_LOGv("MsgSetCorrectionsMeasCorr");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGv("MsgSetCorrectionsMeasCorr::proc()");
+ mApi.setMeasurementCorrections(mGnssMeasCorr);
+ }
+ };
+
+ if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
+ sendMsg(new MsgSetCorrectionsMeasCorr(gnssMeasCorr, *this, *mLocApi));
+ return true;
+ } else {
+ LOC_LOGw("Measurement Corrections are not supported!");
+ return false;
+ }
+}
+uint32_t GnssAdapter::antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback) {
+ LOC_LOGi("GnssAdapter::antennaInfoInitCommand");
+
+ /* Message to initialize Antenna Information */
+ struct MsgInitAi : public LocMsg {
+ const antennaInfoCb mAntennaInfoCb;
+ GnssAdapter& mAdapter;
+
+ inline MsgInitAi(const antennaInfoCb antennaInfoCallback, GnssAdapter& adapter) :
+ LocMsg(), mAntennaInfoCb(antennaInfoCallback), mAdapter(adapter) {
+ LOC_LOGv("MsgInitAi");
+ }
+
+ inline virtual void proc() const {
+ LOC_LOGv("MsgInitAi::proc()");
+ mAdapter.reportGnssAntennaInformation(mAntennaInfoCb);
+ }
+ };
+ if (mIsAntennaInfoInterfaceOpened) {
+ return ANTENNA_INFO_ERROR_ALREADY_INIT;
+ } else {
+ mIsAntennaInfoInterfaceOpened = true;
+ sendMsg(new MsgInitAi(antennaInfoCallback, *this));
+ return ANTENNA_INFO_SUCCESS;
+ }
+}
+
+void
+GnssAdapter::configRobustLocation(uint32_t sessionId,
+ bool enable, bool enableForE911) {
+
+ mLocConfigInfo.robustLocationConfigInfo.isValid = true;
+ mLocConfigInfo.robustLocationConfigInfo.enable = enable;
+ mLocConfigInfo.robustLocationConfigInfo.enableFor911 = enableForE911;
+
+ LocApiResponse* locApiResponse = nullptr;
+ if (sessionId != 0) {
+ locApiResponse =
+ new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+ }
+ mLocApi->configRobustLocation(enable, enableForE911, locApiResponse);
+}
+
+uint32_t GnssAdapter::configRobustLocationCommand(
+ bool enable, bool enableForE911) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgConfigRobustLocation : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ bool mEnable;
+ bool mEnableForE911;
+
+ inline MsgConfigRobustLocation(GnssAdapter& adapter,
+ uint32_t sessionId,
+ bool enable,
+ bool enableForE911) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mEnable(enable),
+ mEnableForE911(enableForE911) {}
+ inline virtual void proc() const {
+ mAdapter.configRobustLocation(mSessionId, mEnable, mEnableForE911);
+ }
+ };
+
+ sendMsg(new MsgConfigRobustLocation(*this, sessionId, enable, enableForE911));
+ return sessionId;
+}
+
+void
+GnssAdapter::configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek) {
+ // suspend all sessions for modem to take the min GPS week config
+ suspendSessions();
+
+ LocApiResponse* locApiResponse = nullptr;
+ if (sessionId != 0) {
+ locApiResponse =
+ new LocApiResponse(*getContext(),
+ [this, sessionId] (LocationError err) {
+ reportResponse(err, sessionId);});
+ if (!locApiResponse) {
+ LOC_LOGe("memory alloc failed");
+ }
+ }
+ mLocApi->configMinGpsWeek(minGpsWeek, locApiResponse);
+
+ // resume all tracking sessions after the min GPS week config
+ // has been changed
+ restartSessions(false);
+}
+
+uint32_t GnssAdapter::configMinGpsWeekCommand(uint16_t minGpsWeek) {
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgConfigMinGpsWeek : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ uint16_t mMinGpsWeek;
+
+ inline MsgConfigMinGpsWeek(GnssAdapter& adapter,
+ uint32_t sessionId,
+ uint16_t minGpsWeek) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mMinGpsWeek(minGpsWeek) {}
+ inline virtual void proc() const {
+ mAdapter.configMinGpsWeek(mSessionId, mMinGpsWeek);
+ }
+ };
+
+ sendMsg(new MsgConfigMinGpsWeek(*this, sessionId, minGpsWeek));
+ return sessionId;
+}
+
+uint32_t GnssAdapter::configDeadReckoningEngineParamsCommand(
+ const DeadReckoningEngineConfig& dreConfig) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGd("session id %u", sessionId);
+
+ struct MsgConfigDrEngine : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ DeadReckoningEngineConfig mDreConfig;
+
+ inline MsgConfigDrEngine(GnssAdapter& adapter,
+ uint32_t sessionId,
+ const DeadReckoningEngineConfig& dreConfig) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mDreConfig(dreConfig) {}
+ inline virtual void proc() const {
+ LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+ if (true == mAdapter.mEngHubProxy->configDeadReckoningEngineParams(mDreConfig)) {
+ err = LOCATION_ERROR_SUCCESS;
+ }
+ mAdapter.reportResponse(err, mSessionId);
+ }
+ };
+
+ sendMsg(new MsgConfigDrEngine(*this, sessionId, dreConfig));
+ return sessionId;
+}
+
+uint32_t GnssAdapter::configEngineRunStateCommand(
+ PositioningEngineMask engType, LocEngineRunState engState) {
+
+ // generated session id will be none-zero
+ uint32_t sessionId = generateSessionId();
+ LOC_LOGe("session id %u, eng type 0x%x, eng state %d, dre enabled %d",
+ sessionId, engType, engState, mDreIntEnabled);
+
+ struct MsgConfigEngineRunState : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ PositioningEngineMask mEngType;
+ LocEngineRunState mEngState;
+
+ inline MsgConfigEngineRunState(GnssAdapter& adapter,
+ uint32_t sessionId,
+ PositioningEngineMask engType,
+ LocEngineRunState engState) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mEngType(engType),
+ mEngState(engState) {}
+ inline virtual void proc() const {
+ LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
+ // Currently, only DR engine supports pause/resume request
+ if ((mEngType == DEAD_RECKONING_ENGINE) &&
+ (mAdapter.mDreIntEnabled == true)) {
+ if (true == mAdapter.mEngHubProxy->configEngineRunState(mEngType, mEngState)) {
+ err = LOCATION_ERROR_SUCCESS;
+ }
+ }
+ mAdapter.reportResponse(err, mSessionId);
+ }
+ };
+
+ sendMsg(new MsgConfigEngineRunState(*this, sessionId, engType, engState));
+
+ return sessionId;
+}
+
+void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig)
+{
+ struct MsgReportGnssConfig : public LocMsg {
+ GnssAdapter& mAdapter;
+ uint32_t mSessionId;
+ mutable GnssConfig mGnssConfig;
+ inline MsgReportGnssConfig(GnssAdapter& adapter,
+ uint32_t sessionId,
+ const GnssConfig& gnssConfig) :
+ LocMsg(),
+ mAdapter(adapter),
+ mSessionId(sessionId),
+ mGnssConfig(gnssConfig) {}
+ inline virtual void proc() const {
+ // Invoke control clients config callback
+ if (nullptr != mAdapter.mControlCallbacks.gnssConfigCb) {
+ mAdapter.mControlCallbacks.gnssConfigCb(mSessionId, mGnssConfig);
+ } else {
+ LOC_LOGe("Failed to report, callback not registered");
+ }
+ }
+ };
+
+ sendMsg(new MsgReportGnssConfig(*this, sessionId, gnssConfig));
+}
+
+/* ==== Eng Hub Proxy ================================================================= */
+/* ======== UTILITIES ================================================================= */
+void
+GnssAdapter::initEngHubProxyCommand() {
+ LOC_LOGD("%s]: ", __func__);
+
+ struct MsgInitEngHubProxy : public LocMsg {
+ GnssAdapter* mAdapter;
+ inline MsgInitEngHubProxy(GnssAdapter* adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ inline virtual void proc() const {
+ mAdapter->initEngHubProxy();
+ }
+ };
+
+ sendMsg(new MsgInitEngHubProxy(this));
+}
+
+bool
+GnssAdapter::initEngHubProxy() {
+ static bool firstTime = true;
+ static bool engHubLoadSuccessful = false;
+
+ const char *error = nullptr;
+ unsigned int processListLength = 0;
+ loc_process_info_s_type* processInfoList = nullptr;
+
+ do {
+ // load eng hub only once
+ if (firstTime == false) {
+ break;
+ }
+
+ int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
+ &processInfoList);
+ if (rc != 0) {
+ LOC_LOGE("%s]: failed to parse conf file", __func__);
+ break;
+ }
+
+ bool pluginDaemonEnabled = false;
+ // go over the conf table to see whether any plugin daemon is enabled
+ for (unsigned int i = 0; i < processListLength; i++) {
+ if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
+ strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
+ (processInfoList[i].proc_status == ENABLED)) {
+ pluginDaemonEnabled = true;
+ // check if this is DRE-INT engine
+ if ((processInfoList[i].args[1]!= nullptr) &&
+ (strncmp(processInfoList[i].args[1], "DRE-INT", sizeof("DRE-INT")) == 0)) {
+ mDreIntEnabled = true;
+ break;
+ }
+ }
+ }
+
+ // no plugin daemon is enabled for this platform,
+ // check if external engine is present for which we need
+ // libloc_eng_hub.so to be loaded
+ if (pluginDaemonEnabled == false) {
+ UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izatConfParamTable);
+ if (!loadEngHubForExternalEngine) {
+ break;
+ }
+ }
+
+ // load the engine hub .so, if the .so is not present
+ // all EngHubProxyBase calls will turn into no-op.
+ void *handle = nullptr;
+ if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
+ if ((error = dlerror()) != nullptr) {
+ LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
+ }
+ break;
+ }
+
+ // prepare the callback functions
+ // callback function for engine hub to report back position event
+ GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
+ [this](int count, EngineLocationInfo* locationArr) {
+ // report from engine hub on behalf of PPE will be treated as fromUlp
+ reportEnginePositionsEvent(count, locationArr);
+ };
+
+ // callback function for engine hub to report back sv event
+ GnssAdapterReportSvEventCb reportSvEventCb =
+ [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
+ reportSvEvent(svNotify, fromEngineHub);
+ };
+
+ // callback function for engine hub to request for complete aiding data
+ GnssAdapterReqAidingDataCb reqAidingDataCb =
+ [this] (const GnssAidingDataSvMask& svDataMask) {
+ mLocApi->requestForAidingData(svDataMask);
+ };
+
+ GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb =
+ [this] (bool nHzNeeded, bool nHzMeasNeeded) {
+
+ if (nHzMeasNeeded &&
+ (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
+ LOC_REGISTRATION_MASK_ENABLED);
+ } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) {
+ updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
+ LOC_REGISTRATION_MASK_DISABLED);
+ }
+
+ if (mNHzNeeded != nHzNeeded) {
+ mNHzNeeded = nHzNeeded;
+ checkAndRestartSPESession();
+ }
+ };
+
+ GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb =
+ [this] (const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
+ reportQwesCapabilities(featureMap);
+ };
+
+ getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
+ if(getter != nullptr) {
+ EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
+ reportPositionEventCb,
+ reportSvEventCb, reqAidingDataCb,
+ updateNHzRequirementCb,
+ updateQwesFeatureStatusCb);
+ if (hubProxy != nullptr) {
+ mEngHubProxy = hubProxy;
+ engHubLoadSuccessful = true;
+ }
+ }
+ else {
+ LOC_LOGD("%s]: entered, did not find function", __func__);
+ }
+
+ LOC_LOGD("%s]: first time initialization %d, returned %d",
+ __func__, firstTime, engHubLoadSuccessful);
+
+ } while (0);
+
+ if (processInfoList != nullptr) {
+ free (processInfoList);
+ processInfoList = nullptr;
+ }
+
+ firstTime = false;
+ return engHubLoadSuccessful;
+}
+
+std::vector<double>
+GnssAdapter::parseDoublesString(char* dString) {
+ std::vector<double> dVector;
+ char* tmp = NULL;
+ char* substr;
+
+ dVector.clear();
+ for (substr = strtok_r(dString, " ", &tmp);
+ substr != NULL;
+ substr = strtok_r(NULL, " ", &tmp)) {
+ dVector.push_back(std::stod(substr));
+ }
+ return dVector;
+}
+
+void
+GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)
+{
+#define MAX_TEXT_WIDTH 50
+#define MAX_COLUMN_WIDTH 20
+
+ /* parse antenna_corrections file and fill in
+ a vector of GnssAntennaInformation data structure */
+
+ std::vector<GnssAntennaInformation> gnssAntennaInformations;
+ GnssAntennaInformation gnssAntennaInfo;
+
+ uint32_t antennaInfoVectorSize;
+ loc_param_s_type ant_info_vector_table[] =
+ {
+ { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
+ };
+ UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
+
+ for (uint32_t i = 0; i < antennaInfoVectorSize; i++) {
+ double carrierFrequencyMHz;
+ char pcOffsetStr[LOC_MAX_PARAM_STRING];
+ uint32_t numberOfRows = 0;
+ uint32_t numberOfColumns = 0;
+ uint32_t numberOfRowsSGC = 0;
+ uint32_t numberOfColumnsSGC = 0;
+
+ gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.clear();
+ gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.clear();
+ gnssAntennaInfo.signalGainCorrectionDbi.clear();
+ gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.clear();
+ string s1 = "CARRIER_FREQUENCY_";
+ s1 += to_string(i);
+ string s2 = "PC_OFFSET_";
+ s2 += to_string(i);
+ string s3 = "NUMBER_OF_ROWS_";
+ s3 += to_string(i);
+ string s4 = "NUMBER_OF_COLUMNS_";
+ s4 += to_string(i);
+ string s5 = "NUMBER_OF_ROWS_SGC_";
+ s5 += to_string(i);
+ string s6 = "NUMBER_OF_COLUMNS_SGC_";
+ s6 += to_string(i);
+
+ gnssAntennaInfo.size = sizeof(gnssAntennaInfo);
+ loc_param_s_type ant_cf_table[] =
+ {
+ { s1.c_str(), &carrierFrequencyMHz, NULL, 'f' },
+ { s2.c_str(), &pcOffsetStr, NULL, 's' },
+ { s3.c_str(), &numberOfRows, NULL, 'n' },
+ { s4.c_str(), &numberOfColumns, NULL, 'n' },
+ { s5.c_str(), &numberOfRowsSGC, NULL, 'n' },
+ { s6.c_str(), &numberOfColumnsSGC, NULL, 'n' },
+ };
+ UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_cf_table);
+
+ if (0 == numberOfRowsSGC) {
+ numberOfRowsSGC = numberOfRows;
+ }
+ if (0 == numberOfColumnsSGC) {
+ numberOfColumnsSGC = numberOfColumns;
+ }
+
+ gnssAntennaInfo.carrierFrequencyMHz = carrierFrequencyMHz;
+
+ // now parse pcOffsetStr to get each entry
+ std::vector<double> pcOffset;
+ pcOffset = parseDoublesString(pcOffsetStr);
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.size =
+ sizeof(gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters);
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x = pcOffset[0];
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty = pcOffset[1];
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y = pcOffset[2];
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty = pcOffset[3];
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4];
+ gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5];
+
+ uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns;
+ uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC;
+ for (uint32_t j = 0; j < numberOfRows; j++) {
+ char pcVarCorrStr[array_size];
+ char pcVarCorrUncStr[array_size];
+
+ string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_";
+ s1 += to_string(j);
+ string s2 = "PC_VARIATION_CORRECTION_UNC_" + to_string(i) + "_ROW_";
+ s2 += to_string(j);
+
+ loc_param_s_type ant_row_table[] =
+ {
+ { s1.c_str(), &pcVarCorrStr, NULL, 's' },
+ { s2.c_str(), &pcVarCorrUncStr, NULL, 's' },
+ };
+ UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size);
+
+ gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back(
+ parseDoublesString(pcVarCorrStr));
+ gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.push_back(
+ parseDoublesString(pcVarCorrUncStr));
+ }
+ for (uint32_t j = 0; j < numberOfRowsSGC; j++) {
+ char sigGainCorrStr[array_size_SGC];
+ char sigGainCorrUncStr[array_size_SGC];
+
+ string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_";
+ s3 += to_string(j);
+ string s4 = "SIGNAL_GAIN_CORRECTION_UNC_" + to_string(i) + "_ROW_";
+ s4 += to_string(j);
+
+ loc_param_s_type ant_row_table[] =
+ {
+ { s3.c_str(), &sigGainCorrStr, NULL, 's' },
+ { s4.c_str(), &sigGainCorrUncStr, NULL, 's' },
+ };
+ UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC);
+
+ gnssAntennaInfo.signalGainCorrectionDbi.push_back(
+ parseDoublesString(sigGainCorrStr));
+ gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.push_back(
+ parseDoublesString(sigGainCorrUncStr));
+ }
+ gnssAntennaInformations.push_back(std::move(gnssAntennaInfo));
+ }
+ antennaInfoCallback(gnssAntennaInformations);
+}
+
+/* ==== DGnss Usable Reporter ========================================================= */
+/* ======== UTILITIES ================================================================= */
+
+void GnssAdapter::initCDFWService()
+{
+ LOC_LOGv("mCdfwInterface %p", mCdfwInterface);
+ if (nullptr == mCdfwInterface) {
+ void* libHandle = nullptr;
+ const char* libName = "libcdfw.so";
+
+ libHandle = nullptr;
+ getCdfwInterface getter = (getCdfwInterface)dlGetSymFromLib(libHandle,
+ libName, "getQCdfwInterface");
+ if (nullptr == getter) {
+ LOC_LOGe("dlGetSymFromLib getQCdfwInterface failed");
+ } else {
+ mCdfwInterface = getter();
+ }
+
+ if (nullptr != mCdfwInterface) {
+ QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) {
+ mDGnssNeedReport = sessionActive;
+ };
+ mCdfwInterface->startDgnssApiService(*mMsgTask);
+ mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb);
+ }
+ }
+}
+
+/*==== DGnss Ntrip Source ==========================================================*/
+void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& params,
+ bool enableRTKEngine) {
+
+ (void)enableRTKEngine; //future parameter, not used
+
+ struct enableNtripMsg : public LocMsg {
+ GnssAdapter& mAdapter;
+ const GnssNtripConnectionParams& mParams;
+
+ inline enableNtripMsg(GnssAdapter& adapter,
+ const GnssNtripConnectionParams& params) :
+ LocMsg(),
+ mAdapter(adapter),
+ mParams(std::move(params)) {}
+ inline virtual void proc() const {
+ mAdapter.handleEnablePPENtrip(mParams);
+ }
+ };
+ sendMsg(new enableNtripMsg(*this, params));
+}
+
+void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) {
+ LOC_LOGd("%d %s %d %s %s %s %d mSendNmeaConsent %d",
+ params.useSSL, params.hostNameOrIp.data(), params.port,
+ params.mountPoint.data(), params.username.data(), params.password.data(),
+ params.requiresNmeaLocation, mSendNmeaConsent);
+
+ GnssNtripConnectionParams* pNtripParams = &(mStartDgnssNtripParams.ntripParams);
+
+ if (pNtripParams->useSSL == params.useSSL &&
+ 0 == pNtripParams->hostNameOrIp.compare(params.hostNameOrIp) &&
+ pNtripParams->port == params.port &&
+ 0 == pNtripParams->mountPoint.compare(params.mountPoint) &&
+ 0 == pNtripParams->username.compare(params.username) &&
+ 0 == pNtripParams->password.compare(params.password) &&
+ pNtripParams->requiresNmeaLocation == params.requiresNmeaLocation &&
+ mDgnssState & DGNSS_STATE_ENABLE_NTRIP_COMMAND) {
+ LOC_LOGd("received same Ntrip param");
+ return;
+ }
+
+ mDgnssState |= DGNSS_STATE_ENABLE_NTRIP_COMMAND;
+ mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+ mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
+
+ mStartDgnssNtripParams.ntripParams = std::move(params);
+ mStartDgnssNtripParams.nmea.clear();
+ if (mSendNmeaConsent && pNtripParams->requiresNmeaLocation) {
+ mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
+ mDgnssLastNmeaBootTimeMilli = 0;
+ return;
+ }
+
+ checkUpdateDgnssNtrip(false);
+}
+
+void GnssAdapter::disablePPENtripStreamCommand() {
+ struct disableNtripMsg : public LocMsg {
+ GnssAdapter& mAdapter;
+
+ inline disableNtripMsg(GnssAdapter& adapter) :
+ LocMsg(),
+ mAdapter(adapter) {}
+ inline virtual void proc() const {
+ mAdapter.handleDisablePPENtrip();
+ }
+ };
+ sendMsg(new disableNtripMsg(*this));
+}
+
+void GnssAdapter::handleDisablePPENtrip() {
+ mDgnssState &= ~DGNSS_STATE_ENABLE_NTRIP_COMMAND;
+ mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+ stopDgnssNtrip();
+}
+
+void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) {
+ LOC_LOGd("isInSession %d mDgnssState 0x%x isLocationValid %d",
+ isInSession(), mDgnssState, isLocationValid);
+ if (isInSession()) {
+ uint64_t curBootTime = getBootTimeMilliSec();
+ if (mDgnssState == (DGNSS_STATE_ENABLE_NTRIP_COMMAND | DGNSS_STATE_NO_NMEA_PENDING)) {
+ mDgnssState |= DGNSS_STATE_NTRIP_SESSION_STARTED;
+ mXtraObserver.startDgnssSource(mStartDgnssNtripParams);
+ if (isDgnssNmeaRequired()) {
+ mDgnssLastNmeaBootTimeMilli = curBootTime;
+ }
+ } else if ((mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) && isLocationValid &&
+ isDgnssNmeaRequired() &&
+ curBootTime - mDgnssLastNmeaBootTimeMilli > DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI ) {
+ mXtraObserver.updateNmeaToDgnssServer(mStartDgnssNtripParams.nmea);
+ mDgnssLastNmeaBootTimeMilli = curBootTime;
+ }
+ }
+}
+
+void GnssAdapter::stopDgnssNtrip() {
+ LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState);
+ mStartDgnssNtripParams.nmea.clear();
+ if (mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) {
+ mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
+ mXtraObserver.stopDgnssSource();
+ }
+}
+
+void GnssAdapter::reportGGAToNtrip(const char* nmea) {
+
+#define POS_OF_GGA (3) //start position of "GGA"
+#define COMMAS_BEFORE_VALID (6) //"$GPGGA,,,,,,0,,,,,,,,*hh"
+
+ if (!isDgnssNmeaRequired()) {
+ return;
+ }
+
+ if (nullptr == nmea || 0 == strlen(nmea)) {
+ return;
+ }
+
+ string nmeaString(nmea);
+ size_t foundPos = nmeaString.find("GGA");
+ size_t foundNth = 0;
+ string GGAString;
+
+ if (foundPos != string::npos && foundPos >= POS_OF_GGA) {
+ size_t foundNextSentence = nmeaString.find("$", foundPos);
+ if (foundNextSentence != string::npos) {
+ /* remove other sentences after GGA */
+ GGAString = nmeaString.substr(foundPos - POS_OF_GGA, foundNextSentence);
+ } else {
+ /* GGA is the last sentence */
+ GGAString = nmeaString.substr(foundPos - POS_OF_GGA);
+ }
+ LOC_LOGd("GGAString %s", GGAString.c_str());
+
+ foundPos = GGAString.find(",");
+ while (foundPos != string::npos && foundNth < COMMAS_BEFORE_VALID) {
+ foundPos++;
+ foundNth++;
+ foundPos = GGAString.find(",", foundPos);
+ }
+
+ if (COMMAS_BEFORE_VALID == foundNth && GGAString.at(foundPos-1) != '0') {
+ mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
+ mStartDgnssNtripParams.nmea = std::move(GGAString);
+ checkUpdateDgnssNtrip(true);
+ }
+ }
+
+ return;
+}
diff --git a/gps/gnss/GnssAdapter.h b/gps/gnss/GnssAdapter.h
new file mode 100644
index 0000000..6b8d024
--- /dev/null
+++ b/gps/gnss/GnssAdapter.h
@@ -0,0 +1,648 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef GNSS_ADAPTER_H
+#define GNSS_ADAPTER_H
+
+#include <LocAdapterBase.h>
+#include <LocContext.h>
+#include <IOsObserver.h>
+#include <EngineHubProxyBase.h>
+#include <LocationAPI.h>
+#include <Agps.h>
+#include <SystemStatus.h>
+#include <XtraSystemStatusObserver.h>
+#include <map>
+#include <functional>
+#include <loc_misc_utils.h>
+#include <queue>
+#include <NativeAgpsHandler.h>
+
+#define MAX_URL_LEN 256
+#define NMEA_SENTENCE_MAX_LENGTH 200
+#define GLONASS_SV_ID_OFFSET 64
+#define MAX_SATELLITES_IN_USE 12
+#define LOC_NI_NO_RESPONSE_TIME 20
+#define LOC_GPS_NI_RESPONSE_IGNORE 4
+#define ODCPI_EXPECTED_INJECTION_TIME_MS 10000
+#define DELETE_AIDING_DATA_EXPECTED_TIME_MS 5000
+
+class GnssAdapter;
+
+typedef std::map<LocationSessionKey, LocationOptions> LocationSessionMap;
+typedef std::map<LocationSessionKey, TrackingOptions> TrackingOptionsMap;
+
+class OdcpiTimer : public LocTimer {
+public:
+ OdcpiTimer(GnssAdapter* adapter) :
+ LocTimer(), mAdapter(adapter), mActive(false) {}
+
+ inline void start() {
+ mActive = true;
+ LocTimer::start(ODCPI_EXPECTED_INJECTION_TIME_MS, false);
+ }
+ inline void stop() {
+ mActive = false;
+ LocTimer::stop();
+ }
+ inline void restart() {
+ stop();
+ start();
+ }
+ inline bool isActive() {
+ return mActive;
+ }
+
+private:
+ // Override
+ virtual void timeOutCallback() override;
+
+ GnssAdapter* mAdapter;
+ bool mActive;
+};
+
+typedef struct {
+ pthread_t thread; /* NI thread */
+ uint32_t respTimeLeft; /* examine time for NI response */
+ bool respRecvd; /* NI User reponse received or not from Java layer*/
+ void* rawRequest;
+ uint32_t reqID; /* ID to check against response */
+ GnssNiResponse resp;
+ pthread_cond_t tCond;
+ pthread_mutex_t tLock;
+ GnssAdapter* adapter;
+} NiSession;
+typedef struct {
+ NiSession session; /* SUPL NI Session */
+ NiSession sessionEs; /* Emergency SUPL NI Session */
+ uint32_t reqIDCounter;
+} NiData;
+
+typedef enum {
+ NMEA_PROVIDER_AP = 0, // Application Processor Provider of NMEA
+ NMEA_PROVIDER_MP // Modem Processor Provider of NMEA
+} NmeaProviderType;
+typedef struct {
+ GnssSvType svType;
+ const char* talker;
+ uint64_t mask;
+ uint32_t svIdOffset;
+} NmeaSvMeta;
+
+typedef struct {
+ double latitude;
+ double longitude;
+ float accuracy;
+ // the CPI will be blocked until the boot time
+ // specified in blockedTillTsMs
+ int64_t blockedTillTsMs;
+ // CPIs whose both latitude and longitude differ
+ // no more than latLonThreshold will be blocked
+ // in units of degree
+ double latLonDiffThreshold;
+} BlockCPIInfo;
+
+typedef struct {
+ bool isValid;
+ bool enable;
+ float tuncThresholdMs; // need to be specified if enable is true
+ uint32_t energyBudget; // need to be specified if enable is true
+} TuncConfigInfo;
+
+typedef struct {
+ bool isValid;
+ bool enable;
+} PaceConfigInfo;
+
+typedef struct {
+ bool isValid;
+ bool enable;
+ bool enableFor911;
+} RobustLocationConfigInfo;
+
+typedef struct {
+ TuncConfigInfo tuncConfigInfo;
+ PaceConfigInfo paceConfigInfo;
+ RobustLocationConfigInfo robustLocationConfigInfo;
+ LeverArmConfigInfo leverArmConfigInfo;
+} LocIntegrationConfigInfo;
+
+using namespace loc_core;
+
+namespace loc_core {
+ class SystemStatus;
+}
+
+typedef std::function<void(
+ uint64_t gnssEnergyConsumedFromFirstBoot
+)> GnssEnergyConsumedCallback;
+
+typedef void* QDgnssListenerHDL;
+typedef std::function<void(
+ bool sessionActive
+)> QDgnssSessionActiveCb;
+
+struct CdfwInterface {
+ void (*startDgnssApiService)(const MsgTask& msgTask);
+ QDgnssListenerHDL (*createUsableReporter)(
+ QDgnssSessionActiveCb sessionActiveCb);
+ void (*destroyUsableReporter)(QDgnssListenerHDL handle);
+ void (*reportUsable)(QDgnssListenerHDL handle, bool usable);
+};
+
+typedef uint16_t DGnssStateBitMask;
+#define DGNSS_STATE_ENABLE_NTRIP_COMMAND 0X01
+#define DGNSS_STATE_NO_NMEA_PENDING 0X02
+#define DGNSS_STATE_NTRIP_SESSION_STARTED 0X04
+
+class GnssReportLoggerUtil {
+public:
+ typedef void (*LogGnssLatency)(const GnssLatencyInfo& gnssLatencyMeasInfo);
+
+ GnssReportLoggerUtil() : mLogLatency(nullptr) {
+ const char* libname = "liblocdiagiface.so";
+ void* libHandle = nullptr;
+ mLogLatency = (LogGnssLatency)dlGetSymFromLib(libHandle, libname, "LogGnssLatency");
+ }
+
+ bool isLogEnabled();
+ void log(const GnssLatencyInfo& gnssLatencyMeasInfo);
+
+private:
+ LogGnssLatency mLogLatency;
+};
+
+class GnssAdapter : public LocAdapterBase {
+
+ /* ==== Engine Hub ===================================================================== */
+ EngineHubProxyBase* mEngHubProxy;
+ bool mNHzNeeded;
+ bool mSPEAlreadyRunningAtHighestInterval;
+
+ /* ==== TRACKING ======================================================================= */
+ TrackingOptionsMap mTimeBasedTrackingSessions;
+ LocationSessionMap mDistanceBasedTrackingSessions;
+ LocPosMode mLocPositionMode;
+ GnssSvUsedInPosition mGnssSvIdUsedInPosition;
+ bool mGnssSvIdUsedInPosAvail;
+ GnssSvMbUsedInPosition mGnssMbSvIdUsedInPosition;
+ bool mGnssMbSvIdUsedInPosAvail;
+
+ /* ==== CONTROL ======================================================================== */
+ LocationControlCallbacks mControlCallbacks;
+ uint32_t mAfwControlId;
+ uint32_t mNmeaMask;
+ uint64_t mPrevNmeaRptTimeNsec;
+ GnssSvIdConfig mGnssSvIdConfig;
+ GnssSvTypeConfig mGnssSeconaryBandConfig;
+ GnssSvTypeConfig mGnssSvTypeConfig;
+ GnssSvTypeConfigCallback mGnssSvTypeConfigCb;
+ bool mSupportNfwControl;
+ LocIntegrationConfigInfo mLocConfigInfo;
+
+ /* ==== NI ============================================================================= */
+ NiData mNiData;
+
+ /* ==== AGPS =========================================================================== */
+ // This must be initialized via initAgps()
+ AgpsManager mAgpsManager;
+ void initAgps(const AgpsCbInfo& cbInfo);
+
+ /* ==== NFW =========================================================================== */
+ NfwStatusCb mNfwCb;
+ IsInEmergencySession mIsE911Session;
+ inline void initNfw(const NfwCbInfo& cbInfo) {
+ mNfwCb = (NfwStatusCb)cbInfo.visibilityControlCb;
+ mIsE911Session = (IsInEmergencySession)cbInfo.isInEmergencySession;
+ }
+
+ /* ==== Measurement Corrections========================================================= */
+ bool mIsMeasCorrInterfaceOpen;
+ measCorrSetCapabilitiesCb mMeasCorrSetCapabilitiesCb;
+ bool initMeasCorr(bool bSendCbWhenNotSupported);
+ bool mIsAntennaInfoInterfaceOpened;
+
+ /* ==== DGNSS Data Usable Report======================================================== */
+ QDgnssListenerHDL mQDgnssListenerHDL;
+ const CdfwInterface* mCdfwInterface;
+ bool mDGnssNeedReport;
+ bool mDGnssDataUsage;
+ void reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet);
+
+ /* ==== ODCPI ========================================================================== */
+ OdcpiRequestCallback mOdcpiRequestCb;
+ bool mOdcpiRequestActive;
+ OdcpiPrioritytype mCallbackPriority;
+ OdcpiTimer mOdcpiTimer;
+ OdcpiRequestInfo mOdcpiRequest;
+ void odcpiTimerExpire();
+
+ /* ==== DELETEAIDINGDATA =============================================================== */
+ int64_t mLastDeleteAidingDataTime;
+
+ /* === SystemStatus ===================================================================== */
+ SystemStatus* mSystemStatus;
+ std::string mServerUrl;
+ std::string mMoServerUrl;
+ XtraSystemStatusObserver mXtraObserver;
+ LocationSystemInfo mLocSystemInfo;
+ std::vector<GnssSvIdSource> mBlacklistedSvIds;
+ PowerStateType mSystemPowerState;
+
+ /* === Misc ===================================================================== */
+ BlockCPIInfo mBlockCPIInfo;
+ bool mPowerOn;
+ uint32_t mAllowFlpNetworkFixes;
+ std::queue<GnssLatencyInfo> mGnssLatencyInfoQueue;
+ GnssReportLoggerUtil mLogger;
+ bool mDreIntEnabled;
+
+ /* === NativeAgpsHandler ======================================================== */
+ NativeAgpsHandler mNativeAgpsHandler;
+
+ /* === Misc callback from QMI LOC API ============================================== */
+ GnssEnergyConsumedCallback mGnssEnergyConsumedCb;
+ std::function<void(bool)> mPowerStateCb;
+
+ /*==== CONVERSION ===================================================================*/
+ static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions);
+ static void convertLocation(Location& out, const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended);
+ static void convertLocationInfo(GnssLocationInfoNotification& out,
+ const GpsLocationExtended& locationExtended,
+ loc_sess_status status);
+ static uint16_t getNumSvUsed(uint64_t svUsedIdsMask,
+ int totalSvCntInThisConstellation);
+
+ /* ======== UTILITIES ================================================================== */
+ inline void initOdcpi(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
+ inline void injectOdcpi(const Location& location);
+ static bool isFlpClient(LocationCallbacks& locationCallbacks);
+
+ /*==== DGnss Ntrip Source ==========================================================*/
+ StartDgnssNtripParams mStartDgnssNtripParams;
+ bool mSendNmeaConsent;
+ DGnssStateBitMask mDgnssState;
+ void checkUpdateDgnssNtrip(bool isLocationValid);
+ void stopDgnssNtrip();
+ uint64_t mDgnssLastNmeaBootTimeMilli;
+
+protected:
+
+ /* ==== CLIENT ========================================================================= */
+ virtual void updateClientsEventMask();
+ virtual void stopClientSessions(LocationAPI* client);
+ inline void setNmeaReportRateConfig();
+ void logLatencyInfo();
+
+public:
+
+ GnssAdapter();
+ virtual inline ~GnssAdapter() { }
+
+ /* ==== SSR ============================================================================ */
+ /* ======== EVENTS ====(Called from QMI Thread)========================================= */
+ virtual void handleEngineUpEvent();
+ /* ======== UTILITIES ================================================================== */
+ void restartSessions(bool modemSSR = false);
+ void checkAndRestartTimeBasedSession();
+ void checkAndRestartSPESession();
+ void suspendSessions();
+
+ /* ==== CLIENT ========================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ virtual void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks);
+
+ /* ==== TRACKING ======================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ uint32_t startTrackingCommand(
+ LocationAPI* client, TrackingOptions& trackingOptions);
+ void updateTrackingOptionsCommand(
+ LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions);
+ void stopTrackingCommand(LocationAPI* client, uint32_t id);
+ /* ======== RESPONSES ================================================================== */
+ void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId);
+ /* ======== UTILITIES ================================================================== */
+ bool isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId);
+ bool isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId);
+ bool hasCallbacksToStartTracking(LocationAPI* client);
+ bool isTrackingSession(LocationAPI* client, uint32_t sessionId);
+ void saveTrackingSession(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& trackingOptions);
+ void eraseTrackingSession(LocationAPI* client, uint32_t sessionId);
+
+ bool setLocPositionMode(const LocPosMode& mode);
+ LocPosMode& getLocPositionMode() { return mLocPositionMode; }
+
+ bool startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& trackingOptions);
+ void startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& trackingOptions);
+ bool stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id);
+ void stopTracking(LocationAPI* client, uint32_t id);
+ bool updateTrackingMultiplex(LocationAPI* client, uint32_t id,
+ const TrackingOptions& trackingOptions);
+ void updateTracking(LocationAPI* client, uint32_t sessionId,
+ const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions);
+ bool checkAndSetSPEToRunforNHz(TrackingOptions & out);
+
+ void setConstrainedTunc(bool enable, float tuncConstraint,
+ uint32_t energyBudget, uint32_t sessionId);
+ void setPositionAssistedClockEstimator(bool enable, uint32_t sessionId);
+ void gnssUpdateSvConfig(uint32_t sessionId,
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig);
+
+ void gnssUpdateSecondaryBandConfig(
+ uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig);
+ void gnssGetSecondaryBandConfig(uint32_t sessionId);
+ void resetSvConfig(uint32_t sessionId);
+ void configLeverArm(uint32_t sessionId, const LeverArmConfigInfo& configInfo);
+ void configRobustLocation(uint32_t sessionId, bool enable, bool enableForE911);
+ void configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek);
+
+ /* ==== NI ============================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void gnssNiResponseCommand(LocationAPI* client, uint32_t id, GnssNiResponse response);
+ /* ======================(Called from NI Thread)======================================== */
+ void gnssNiResponseCommand(GnssNiResponse response, void* rawRequest);
+ /* ======== UTILITIES ================================================================== */
+ bool hasNiNotifyCallback(LocationAPI* client);
+ NiData& getNiData() { return mNiData; }
+
+ /* ==== CONTROL CLIENT ================================================================= */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ uint32_t enableCommand(LocationTechnologyType techType);
+ void disableCommand(uint32_t id);
+ void setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks);
+ void readConfigCommand();
+ void requestUlpCommand();
+ void initEngHubProxyCommand();
+ uint32_t* gnssUpdateConfigCommand(const GnssConfig& config);
+ uint32_t* gnssGetConfigCommand(GnssConfigFlagsMask mask);
+ uint32_t gnssDeleteAidingDataCommand(GnssAidingData& data);
+ void deleteAidingData(const GnssAidingData &data, uint32_t sessionId);
+ void gnssUpdateXtraThrottleCommand(const bool enabled);
+ std::vector<LocationError> gnssUpdateConfig(const std::string& oldMoServerUrl,
+ GnssConfig& gnssConfigRequested,
+ GnssConfig& gnssConfigNeedEngineUpdate, size_t count = 0);
+
+ /* ==== GNSS SV TYPE CONFIG ============================================================ */
+ /* ==== COMMANDS ====(Called from Client Thread)======================================== */
+ /* ==== These commands are received directly from client bypassing Location API ======== */
+ void gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config);
+ void gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback);
+ void gnssResetSvTypeConfigCommand();
+
+ /* ==== UTILITIES ====================================================================== */
+ LocationError gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds);
+ LocationError gnssSvIdConfigUpdateSync();
+ void gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds);
+ void gnssSvIdConfigUpdate();
+ void gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config);
+ void gnssSvTypeConfigUpdate(bool sendReset = false);
+ inline void gnssSetSvTypeConfig(const GnssSvTypeConfig& config)
+ { mGnssSvTypeConfig = config; }
+ inline void gnssSetSvTypeConfigCallback(GnssSvTypeConfigCallback callback)
+ { mGnssSvTypeConfigCb = callback; }
+ inline GnssSvTypeConfigCallback gnssGetSvTypeConfigCallback()
+ { return mGnssSvTypeConfigCb; }
+ void setConfig();
+ void gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse= nullptr);
+
+ /* ========= AGPS ====================================================================== */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void initDefaultAgpsCommand();
+ void initAgpsCommand(const AgpsCbInfo& cbInfo);
+ void initNfwCommand(const NfwCbInfo& cbInfo);
+ void dataConnOpenCommand(AGpsExtType agpsType,
+ const char* apnName, int apnLen, AGpsBearerType bearerType);
+ void dataConnClosedCommand(AGpsExtType agpsType);
+ void dataConnFailedCommand(AGpsExtType agpsType);
+ void getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb);
+ void nfwControlCommand(bool enable);
+ uint32_t setConstrainedTuncCommand (bool enable, float tuncConstraint,
+ uint32_t energyBudget);
+ uint32_t setPositionAssistedClockEstimatorCommand (bool enable);
+ uint32_t gnssUpdateSvConfigCommand(const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig);
+ uint32_t gnssUpdateSecondaryBandConfigCommand(
+ const GnssSvTypeConfig& secondaryBandConfig);
+ uint32_t gnssGetSecondaryBandConfigCommand();
+ uint32_t configLeverArmCommand(const LeverArmConfigInfo& configInfo);
+ uint32_t configRobustLocationCommand(bool enable, bool enableForE911);
+ bool openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+ bool measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr);
+ inline void closeMeasCorrCommand() { mIsMeasCorrInterfaceOpen = false; }
+ uint32_t antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback);
+ inline void antennaInfoCloseCommand() { mIsAntennaInfoInterfaceOpened = false; }
+ uint32_t configMinGpsWeekCommand(uint16_t minGpsWeek);
+ uint32_t configDeadReckoningEngineParamsCommand(const DeadReckoningEngineConfig& dreConfig);
+ uint32_t configEngineRunStateCommand(PositioningEngineMask engType,
+ LocEngineRunState engState);
+
+ /* ========= ODCPI ===================================================================== */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void initOdcpiCommand(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
+ void injectOdcpiCommand(const Location& location);
+ /* ======== RESPONSES ================================================================== */
+ void reportResponse(LocationError err, uint32_t sessionId);
+ void reportResponse(size_t count, LocationError* errs, uint32_t* ids);
+ /* ======== UTILITIES ================================================================== */
+ LocationControlCallbacks& getControlCallbacks() { return mControlCallbacks; }
+ void setControlCallbacks(const LocationControlCallbacks& controlCallbacks)
+ { mControlCallbacks = controlCallbacks; }
+ void setAfwControlId(uint32_t id) { mAfwControlId = id; }
+ uint32_t getAfwControlId() { return mAfwControlId; }
+ virtual bool isInSession() { return !mTimeBasedTrackingSessions.empty(); }
+ void initDefaultAgps();
+ bool initEngHubProxy();
+ void initCDFWService();
+ void odcpiTimerExpireEvent();
+
+ /* ==== REPORTS ======================================================================== */
+ /* ======== EVENTS ====(Called from QMI/EngineHub Thread)===================================== */
+ virtual void reportPositionEvent(const UlpLocation& ulpLocation,
+ const GpsLocationExtended& locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask techMask,
+ GnssDataNotification* pDataNotify = nullptr,
+ int msInWeek = -1);
+ virtual void reportEnginePositionsEvent(unsigned int count,
+ EngineLocationInfo* locationArr);
+
+ virtual void reportSvEvent(const GnssSvNotification& svNotify,
+ bool fromEngineHub=false);
+ virtual void reportNmeaEvent(const char* nmea, size_t length);
+ virtual void reportDataEvent(const GnssDataNotification& dataNotify, int msInWeek);
+ virtual bool requestNiNotifyEvent(const GnssNiNotification& notify, const void* data,
+ const LocInEmergency emergencyState);
+ virtual void reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
+ int msInWeek);
+ virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial);
+ virtual void reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris);
+ virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config);
+ virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config);
+ virtual void reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig);
+ virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
+ virtual void reportLocationSystemInfoEvent(const LocationSystemInfo& locationSystemInfo);
+
+ virtual bool requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask);
+ virtual bool releaseATL(int connHandle);
+ virtual bool requestOdcpiEvent(OdcpiRequestInfo& request);
+ virtual bool reportDeleteAidingDataEvent(GnssAidingData& aidingData);
+ virtual bool reportKlobucharIonoModelEvent(GnssKlobucharIonoModel& ionoModel);
+ virtual bool reportGnssAdditionalSystemInfoEvent(
+ GnssAdditionalSystemInfo& additionalSystemInfo);
+ virtual void reportNfwNotificationEvent(GnssNfwNotification& notification);
+ virtual void reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo);
+ virtual bool reportQwesCapabilities
+ (
+ const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
+ );
+
+ /* ======== UTILITIES ================================================================= */
+ bool needReportForGnssClient(const UlpLocation& ulpLocation,
+ enum loc_sess_status status, LocPosTechMask techMask);
+ bool needReportForFlpClient(enum loc_sess_status status, LocPosTechMask techMask);
+ bool needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
+ const struct timespec32_t &apTimeStamp);
+ void reportPosition(const UlpLocation &ulpLocation,
+ const GpsLocationExtended &locationExtended,
+ enum loc_sess_status status,
+ LocPosTechMask techMask);
+ void reportEnginePositions(unsigned int count,
+ const EngineLocationInfo* locationArr);
+ void reportSv(GnssSvNotification& svNotify);
+ void reportNmea(const char* nmea, size_t length);
+ void reportData(GnssDataNotification& dataNotify);
+ bool requestNiNotify(const GnssNiNotification& notify, const void* data,
+ const bool bInformNiAccept);
+ void reportGnssMeasurementData(const GnssMeasurementsNotification& measurements);
+ void reportGnssSvIdConfig(const GnssSvIdConfig& config);
+ void reportGnssSvTypeConfig(const GnssSvTypeConfig& config);
+ void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig);
+ void requestOdcpi(const OdcpiRequestInfo& request);
+ void invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot);
+ void saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb);
+ void reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo);
+ inline void reportNfwNotification(const GnssNfwNotification& notification) {
+ if (NULL != mNfwCb) {
+ mNfwCb(notification);
+ }
+ }
+ inline bool getE911State(void) {
+ if (NULL != mIsE911Session) {
+ return mIsE911Session();
+ }
+ return false;
+ }
+
+ void updateSystemPowerState(PowerStateType systemPowerState);
+ void reportSvPolynomial(const GnssSvPolynomial &svPolynomial);
+
+
+ std::vector<double> parseDoublesString(char* dString);
+ void reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback);
+
+ /*======== GNSSDEBUG ================================================================*/
+ bool getDebugReport(GnssDebugReport& report);
+ /* get AGC information from system status and fill it */
+ void getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek);
+ /* get Data information from system status and fill it */
+ void getDataInformation(GnssDataNotification& data, int msInWeek);
+
+ /*==== SYSTEM STATUS ================================================================*/
+ inline SystemStatus* getSystemStatus(void) { return mSystemStatus; }
+ std::string& getServerUrl(void) { return mServerUrl; }
+ std::string& getMoServerUrl(void) { return mMoServerUrl; }
+
+ /*==== CONVERSION ===================================================================*/
+ static uint32_t convertSuplVersion(const GnssConfigSuplVersion suplVersion);
+ static uint32_t convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl);
+ static uint32_t convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices);
+ static uint32_t convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask);
+ static uint32_t convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask);
+ static uint32_t convertAGloProt(const GnssConfigAGlonassPositionProtocolMask);
+ static uint32_t convertSuplMode(const GnssConfigSuplModeMask suplModeMask);
+ static void convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
+ const GnssSvType& in_constellation,
+ const SystemStatusReports& in);
+ static bool convertToGnssSvIdConfig(
+ const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config);
+ static void convertFromGnssSvIdConfig(
+ const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds);
+ static void convertGnssSvIdMaskToList(
+ uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
+ GnssSvId initialSvId, GnssSvType svType);
+ static void computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
+ const LeverArmConfigInfo& leverArmConfigInfo);
+
+ void injectLocationCommand(double latitude, double longitude, float accuracy);
+ void injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo);
+
+ void injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty);
+ void blockCPICommand(double latitude, double longitude, float accuracy,
+ int blockDurationMsec, double latLonDiffThreshold);
+
+ /* ==== MISCELLANEOUS ================================================================== */
+ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
+ void getPowerStateChangesCommand(std::function<void(bool)> powerStateCb);
+ /* ======== UTILITIES ================================================================== */
+ void reportPowerStateIfChanged();
+ void savePowerStateCallback(std::function<void(bool)> powerStateCb){
+ mPowerStateCb = powerStateCb; }
+ bool getPowerState() { return mPowerOn; }
+ inline PowerStateType getSystemPowerState() { return mSystemPowerState; }
+
+ void setAllowFlpNetworkFixes(uint32_t allow) { mAllowFlpNetworkFixes = allow; }
+ uint32_t getAllowFlpNetworkFixes() { return mAllowFlpNetworkFixes; }
+ void setSuplHostServer(const char* server, int port, LocServerType type);
+ void notifyClientOfCachedLocationSystemInfo(LocationAPI* client,
+ const LocationCallbacks& callbacks);
+ LocationCapabilitiesMask getCapabilities();
+ void updateSystemPowerStateCommand(PowerStateType systemPowerState);
+
+ /*==== DGnss Usable Report Flag ====================================================*/
+ inline void setDGnssUsableFLag(bool dGnssNeedReport) { mDGnssNeedReport = dGnssNeedReport;}
+ inline bool isNMEAPrintEnabled() {
+ return ((mContext != NULL) && (0 != mContext->mGps_conf.ENABLE_NMEA_PRINT));
+ }
+
+ /*==== DGnss Ntrip Source ==========================================================*/
+ void updateNTRIPGGAConsentCommand(bool consentAccepted) { mSendNmeaConsent = consentAccepted; }
+ void enablePPENtripStreamCommand(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+ void disablePPENtripStreamCommand();
+ void handleEnablePPENtrip(const GnssNtripConnectionParams& params);
+ void handleDisablePPENtrip();
+ void reportGGAToNtrip(const char* nmea);
+ inline bool isDgnssNmeaRequired() { return mSendNmeaConsent &&
+ mStartDgnssNtripParams.ntripParams.requiresNmeaLocation;}
+};
+
+#endif //GNSS_ADAPTER_H
diff --git a/gps/gnss/Makefile.am b/gps/gnss/Makefile.am
new file mode 100644
index 0000000..dd313a1
--- /dev/null
+++ b/gps/gnss/Makefile.am
@@ -0,0 +1,32 @@
+AM_CFLAGS = \
+ $(LOCPLA_CFLAGS) \
+ $(LOCHAL_CFLAGS) \
+ $(GPSUTILS_CFLAGS) \
+ $(LOCCORE_CFLAGS) \
+ -I./ \
+ -I../utils \
+ -I$(WORKSPACE)/hardware/qcom/gps/core/data-items \
+ -I../location \
+ -std=c++1y
+
+libgnss_la_SOURCES = \
+ location_gnss.cpp \
+ GnssAdapter.cpp \
+ XtraSystemStatusObserver.cpp \
+ Agps.cpp \
+ NativeAgpsHandler.cpp
+
+if USE_GLIB
+libgnss_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
+libgnss_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -avoid-version
+libgnss_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
+else
+libgnss_la_CFLAGS = $(AM_CFLAGS)
+libgnss_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
+libgnss_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+libgnss_la_LIBADD = -lstdc++ -ldl $(GPSUTILS_LIBS) $(LOCCORE_LIBS)
+
+#Create and Install libraries
+lib_LTLIBRARIES = libgnss.la
diff --git a/gps/gnss/NativeAgpsHandler.cpp b/gps/gnss/NativeAgpsHandler.cpp
new file mode 100644
index 0000000..ce4c03a
--- /dev/null
+++ b/gps/gnss/NativeAgpsHandler.cpp
@@ -0,0 +1,127 @@
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_NativeAgpsHandler"
+
+#include <LocAdapterBase.h>
+#include <SystemStatus.h>
+#include <DataItemId.h>
+#include <DataItemsFactoryProxy.h>
+#include <DataItemConcreteTypesBase.h>
+#include <loc_log.h>
+#include <NativeAgpsHandler.h>
+#include <GnssAdapter.h>
+
+using namespace loc_core;
+
+// IDataItemObserver overrides
+void NativeAgpsHandler::getName(string& name) {
+ name = "NativeAgpsHandler";
+}
+
+void NativeAgpsHandler::notify(const list<IDataItemCore*>& dlist) {
+ for (auto each : dlist) {
+ switch (each->getId()) {
+ case NETWORKINFO_DATA_ITEM_ID: {
+ NetworkInfoDataItemBase* networkInfo =
+ static_cast<NetworkInfoDataItemBase*>(each);
+ uint64_t mobileBit = (uint64_t )1 << loc_core::TYPE_MOBILE;
+ uint64_t allTypes = networkInfo->mAllTypes;
+ mConnected = ((networkInfo->mAllTypes & mobileBit) == mobileBit);
+ /**
+ * mApn Telephony preferred Access Point Name to use for
+ * carrier data connection when connected to a cellular network.
+ * Empty string, otherwise.
+ */
+ mApn = networkInfo->mApn;
+ LOC_LOGd("updated mConnected:%d, mApn: %s", mConnected, mApn.c_str());
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+NativeAgpsHandler* NativeAgpsHandler::sLocalHandle = nullptr;
+NativeAgpsHandler::NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter) :
+ mSystemStatusObsrvr(sysStatObs), mConnected(false), mAdapter(adapter) {
+ sLocalHandle = this;
+ list<DataItemId> subItemIdList = {NETWORKINFO_DATA_ITEM_ID};
+ mSystemStatusObsrvr->subscribe(subItemIdList, this);
+}
+
+NativeAgpsHandler::~NativeAgpsHandler() {
+ if (nullptr != mSystemStatusObsrvr) {
+ LOC_LOGd("Unsubscribe for network info.");
+ list<DataItemId> subItemIdList = {NETWORKINFO_DATA_ITEM_ID};
+ mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
+ }
+ sLocalHandle = nullptr;
+ mSystemStatusObsrvr = nullptr;
+}
+
+
+AgpsCbInfo NativeAgpsHandler::getAgpsCbInfo() {
+ AgpsCbInfo nativeCbInfo = {};
+ nativeCbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
+ nativeCbInfo.atlType = AGPS_ATL_TYPE_WWAN;
+ return nativeCbInfo;
+}
+
+void NativeAgpsHandler::agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo) {
+ if (nullptr != sLocalHandle) {
+ sLocalHandle->processATLRequestRelease(statusInfo);
+ } else {
+ LOC_LOGe("sLocalHandle is null");
+ }
+}
+
+void NativeAgpsHandler::processATLRequestRelease(AGnssExtStatusIpV4 statusInfo) {
+ if (LOC_AGPS_TYPE_WWAN_ANY == statusInfo.type) {
+ LOC_LOGd("status.type = %d status.apnTypeMask = 0x%X", statusInfo.type,
+ statusInfo.apnTypeMask);
+ switch (statusInfo.status) {
+ case LOC_GPS_REQUEST_AGPS_DATA_CONN:
+ if (mConnected) {
+ mAdapter.dataConnOpenCommand(LOC_AGPS_TYPE_WWAN_ANY, mApn.c_str(), mApn.size(),
+ AGPS_APN_BEARER_IPV4);
+ } else {
+ mAdapter.dataConnFailedCommand(LOC_AGPS_TYPE_WWAN_ANY);
+ }
+ break;
+ case LOC_GPS_RELEASE_AGPS_DATA_CONN:
+ mAdapter.dataConnClosedCommand(LOC_AGPS_TYPE_WWAN_ANY);
+ break;
+ default:
+ LOC_LOGe("Invalid Request: %d", statusInfo.status);
+ }
+ } else {
+ LOC_LOGe("mAgpsManger is null or invalid request type!");
+ }
+}
diff --git a/gps/gnss/NativeAgpsHandler.h b/gps/gnss/NativeAgpsHandler.h
new file mode 100644
index 0000000..fb0b46c
--- /dev/null
+++ b/gps/gnss/NativeAgpsHandler.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NATIVEAGPSHANDLER_H
+#define NATIVEAGPSHANDLER_H
+
+#include <cinttypes>
+#include <string.h>
+#include <gps_extended_c.h>
+#include <IDataItemObserver.h>
+#include <IDataItemCore.h>
+#include <IOsObserver.h>
+
+using namespace std;
+using loc_core::IOsObserver;
+using loc_core::IDataItemObserver;
+using loc_core::IDataItemCore;
+
+class GnssAdapter;
+
+class NativeAgpsHandler : public IDataItemObserver {
+public:
+ NativeAgpsHandler(IOsObserver* sysStatObs, GnssAdapter& adapter);
+ ~NativeAgpsHandler();
+ AgpsCbInfo getAgpsCbInfo();
+ // IDataItemObserver overrides
+ virtual void notify(const list<IDataItemCore*>& dlist);
+ inline virtual void getName(string& name);
+private:
+ static NativeAgpsHandler* sLocalHandle;
+ static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 statusInfo);
+ void processATLRequestRelease(AGnssExtStatusIpV4 statusInfo);
+ IOsObserver* mSystemStatusObsrvr;
+ bool mConnected;
+ string mApn;
+ GnssAdapter& mAdapter;
+};
+
+#endif // NATIVEAGPSHANDLER_H
diff --git a/gps/gnss/XtraSystemStatusObserver.cpp b/gps/gnss/XtraSystemStatusObserver.cpp
new file mode 100644
index 0000000..d65622f
--- /dev/null
+++ b/gps/gnss/XtraSystemStatusObserver.cpp
@@ -0,0 +1,384 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_TAG "LocSvc_XtraSystemStatusObs"
+
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <math.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string>
+#include <loc_log.h>
+#include <loc_nmea.h>
+#include <SystemStatus.h>
+#include <vector>
+#include <sstream>
+#include <XtraSystemStatusObserver.h>
+#include <LocAdapterBase.h>
+#include <DataItemId.h>
+#include <DataItemsFactoryProxy.h>
+#include <DataItemConcreteTypesBase.h>
+
+using namespace loc_util;
+using namespace loc_core;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "LocSvc_XSSO"
+
+class XtraIpcListener : public ILocIpcListener {
+ IOsObserver* mSystemStatusObsrvr;
+ const MsgTask* mMsgTask;
+ XtraSystemStatusObserver& mXSSO;
+public:
+ inline XtraIpcListener(IOsObserver* observer, const MsgTask* msgTask,
+ XtraSystemStatusObserver& xsso) :
+ mSystemStatusObsrvr(observer), mMsgTask(msgTask), mXSSO(xsso) {}
+ virtual void onReceive(const char* data, uint32_t length,
+ const LocIpcRecver* recver) override {
+#define STRNCMP(str, constStr) strncmp(str, constStr, sizeof(constStr)-1)
+ if (!STRNCMP(data, "ping")) {
+ LOC_LOGd("ping received");
+#ifdef USE_GLIB
+ } else if (!STRNCMP(data, "connectBackhaul")) {
+ char clientName[30] = {0};
+ sscanf(data, "%*s %29s", clientName);
+ mSystemStatusObsrvr->connectBackhaul(string(clientName));
+ } else if (!STRNCMP(data, "disconnectBackhaul")) {
+ char clientName[30] = {0};
+ sscanf(data, "%*s %29s", clientName);
+ mSystemStatusObsrvr->disconnectBackhaul(string(clientName));
+#endif
+ } else if (!STRNCMP(data, "requestStatus")) {
+ int32_t xtraStatusUpdated = 0;
+ sscanf(data, "%*s %d", &xtraStatusUpdated);
+
+ struct HandleStatusRequestMsg : public LocMsg {
+ XtraSystemStatusObserver& mXSSO;
+ int32_t mXtraStatusUpdated;
+ inline HandleStatusRequestMsg(XtraSystemStatusObserver& xsso,
+ int32_t xtraStatusUpdated) :
+ mXSSO(xsso), mXtraStatusUpdated(xtraStatusUpdated) {}
+ inline void proc() const override {
+ mXSSO.onStatusRequested(mXtraStatusUpdated);
+ /* SSR for DGnss Ntrip Source*/
+ mXSSO.restartDgnssSource();
+ }
+ };
+ mMsgTask->sendMsg(new HandleStatusRequestMsg(mXSSO, xtraStatusUpdated));
+ } else {
+ LOC_LOGw("unknown event: %s", data);
+ }
+ }
+};
+
+XtraSystemStatusObserver::XtraSystemStatusObserver(IOsObserver* sysStatObs,
+ const MsgTask* msgTask) :
+ mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask),
+ mGpsLock(-1), mConnections(~0), mXtraThrottle(true),
+ mReqStatusReceived(false),
+ mIsConnectivityStatusKnown(false),
+ mSender(LocIpc::getLocIpcLocalSender(LOC_IPC_XTRA)),
+ mDelayLocTimer(*mSender) {
+ subscribe(true);
+ auto recver = LocIpc::getLocIpcLocalRecver(
+ make_shared<XtraIpcListener>(sysStatObs, msgTask, *this),
+ LOC_IPC_HAL);
+ mIpc.startNonBlockingListening(recver);
+ mDelayLocTimer.start(100 /*.1 sec*/, false);
+}
+
+bool XtraSystemStatusObserver::updateLockStatus(GnssConfigGpsLock lock) {
+ // mask NI(NFW bit) since from XTRA's standpoint GPS is enabled if
+ // MO(AFW bit) is enabled and disabled when MO is disabled
+ mGpsLock = lock & ~GNSS_CONFIG_GPS_LOCK_NI;
+
+ if (!mReqStatusReceived) {
+ return true;
+ }
+
+ stringstream ss;
+ ss << "gpslock";
+ ss << " " << mGpsLock;
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections,
+ NetworkInfoType* networkHandleInfo) {
+ mIsConnectivityStatusKnown = true;
+ mConnections = allConnections;
+
+ LOC_LOGd("updateConnections mConnections:%" PRIx64, mConnections);
+ for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
+ mNetworkHandle[i] = networkHandleInfo[i];
+ LOC_LOGd("updateConnections [%d] networkHandle:%" PRIx64 " networkType:%u",
+ i, mNetworkHandle[i].networkHandle, mNetworkHandle[i].networkType);
+ }
+
+ if (!mReqStatusReceived) {
+ return true;
+ }
+
+ stringstream ss;
+ ss << "connection" << endl << mConnections << endl
+ << mNetworkHandle[0].toString() << endl
+ << mNetworkHandle[1].toString() << endl
+ << mNetworkHandle[2].toString() << endl
+ << mNetworkHandle[3].toString() << endl
+ << mNetworkHandle[4].toString() << endl
+ << mNetworkHandle[5].toString() << endl
+ << mNetworkHandle[6].toString() << endl
+ << mNetworkHandle[7].toString() << endl
+ << mNetworkHandle[8].toString() << endl
+ << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString();
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+bool XtraSystemStatusObserver::updateTac(const string& tac) {
+ mTac = tac;
+
+ if (!mReqStatusReceived) {
+ return true;
+ }
+
+ stringstream ss;
+ ss << "tac";
+ ss << " " << tac.c_str();
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) {
+ mMccmnc = mccmnc;
+
+ if (!mReqStatusReceived) {
+ return true;
+ }
+
+ stringstream ss;
+ ss << "mncmcc";
+ ss << " " << mccmnc.c_str();
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) {
+ mXtraThrottle = enabled;
+
+ if (!mReqStatusReceived) {
+ return true;
+ }
+
+ stringstream ss;
+ ss << "xtrathrottle";
+ ss << " " << (enabled ? 1 : 0);
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdated) {
+ mReqStatusReceived = true;
+
+ if (xtraStatusUpdated) {
+ return true;
+ }
+
+ stringstream ss;
+
+ ss << "respondStatus" << endl;
+ (mGpsLock == -1 ? ss : ss << mGpsLock) << endl;
+ (mConnections == (uint64_t)~0 ? ss : ss << mConnections) << endl
+ << mNetworkHandle[0].toString() << endl
+ << mNetworkHandle[1].toString() << endl
+ << mNetworkHandle[2].toString() << endl
+ << mNetworkHandle[3].toString() << endl
+ << mNetworkHandle[4].toString() << endl
+ << mNetworkHandle[5].toString() << endl
+ << mNetworkHandle[6].toString() << endl
+ << mNetworkHandle[7].toString() << endl
+ << mNetworkHandle[8].toString() << endl
+ << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString() << endl
+ << mTac << endl << mMccmnc << endl << mIsConnectivityStatusKnown;
+
+ string s = ss.str();
+ return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
+}
+
+void XtraSystemStatusObserver::startDgnssSource(const StartDgnssNtripParams& params) {
+ stringstream ss;
+ const GnssNtripConnectionParams* ntripParams = &(params.ntripParams);
+
+ ss << "startDgnssSource" << endl;
+ ss << ntripParams->useSSL << endl;
+ ss << ntripParams->hostNameOrIp.data() << endl;
+ ss << ntripParams->port << endl;
+ ss << ntripParams->mountPoint.data() << endl;
+ ss << ntripParams->username.data() << endl;
+ ss << ntripParams->password.data() << endl;
+ if (ntripParams->requiresNmeaLocation && !params.nmea.empty()) {
+ ss << params.nmea.data() << endl;
+ }
+ string s = ss.str();
+
+ LOC_LOGd("%s", s.data());
+ LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
+ // make a local copy of the string for SSR
+ mNtripParamsString.assign(std::move(s));
+}
+
+void XtraSystemStatusObserver::restartDgnssSource() {
+ if (!mNtripParamsString.empty()) {
+ LocIpc::send(*mSender,
+ (const uint8_t*)mNtripParamsString.data(), mNtripParamsString.size());
+ LOC_LOGv("Xtra SSR %s", mNtripParamsString.data());
+ }
+}
+
+void XtraSystemStatusObserver::stopDgnssSource() {
+ LOC_LOGv();
+ mNtripParamsString.clear();
+
+ const char s[] = "stopDgnssSource";
+ LocIpc::send(*mSender, (const uint8_t*)s, strlen(s));
+}
+
+void XtraSystemStatusObserver::updateNmeaToDgnssServer(const string& nmea)
+{
+ stringstream ss;
+ ss << "updateDgnssServerNmea" << endl;
+ ss << nmea.data() << endl;
+
+ string s = ss.str();
+ LOC_LOGd("%s", s.data());
+ LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
+}
+
+void XtraSystemStatusObserver::subscribe(bool yes)
+{
+ // Subscription data list
+ list<DataItemId> subItemIdList;
+ subItemIdList.push_back(NETWORKINFO_DATA_ITEM_ID);
+ subItemIdList.push_back(MCCMNC_DATA_ITEM_ID);
+
+ if (yes) {
+ mSystemStatusObsrvr->subscribe(subItemIdList, this);
+
+ list<DataItemId> reqItemIdList;
+ reqItemIdList.push_back(TAC_DATA_ITEM_ID);
+
+ mSystemStatusObsrvr->requestData(reqItemIdList, this);
+
+ } else {
+ mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
+ }
+}
+
+// IDataItemObserver overrides
+void XtraSystemStatusObserver::getName(string& name)
+{
+ name = "XtraSystemStatusObserver";
+}
+
+void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist)
+{
+ struct HandleOsObserverUpdateMsg : public LocMsg {
+ XtraSystemStatusObserver* mXtraSysStatObj;
+ list <IDataItemCore*> mDataItemList;
+
+ inline HandleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs,
+ const list<IDataItemCore*>& dataItemList) :
+ mXtraSysStatObj(xtraSysStatObs) {
+ for (auto eachItem : dataItemList) {
+ IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(
+ eachItem->getId());
+ if (NULL == dataitem) {
+ break;
+ }
+ // Copy the contents of the data item
+ dataitem->copy(eachItem);
+
+ mDataItemList.push_back(dataitem);
+ }
+ }
+
+ inline ~HandleOsObserverUpdateMsg() {
+ for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) {
+ if (*itor != nullptr) {
+ delete *itor;
+ *itor = nullptr;
+ }
+ }
+ }
+
+ inline void proc() const {
+ for (auto each : mDataItemList) {
+ switch (each->getId())
+ {
+ case NETWORKINFO_DATA_ITEM_ID:
+ {
+ NetworkInfoDataItemBase* networkInfo =
+ static_cast<NetworkInfoDataItemBase*>(each);
+ NetworkInfoType* networkHandleInfo =
+ static_cast<NetworkInfoType*>(networkInfo->getNetworkHandle());
+ mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(),
+ networkHandleInfo);
+ }
+ break;
+
+ case TAC_DATA_ITEM_ID:
+ {
+ TacDataItemBase* tac =
+ static_cast<TacDataItemBase*>(each);
+ mXtraSysStatObj->updateTac(tac->mValue);
+ }
+ break;
+
+ case MCCMNC_DATA_ITEM_ID:
+ {
+ MccmncDataItemBase* mccmnc =
+ static_cast<MccmncDataItemBase*>(each);
+ mXtraSysStatObj->updateMccMnc(mccmnc->mValue);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ };
+ mMsgTask->sendMsg(new (nothrow) HandleOsObserverUpdateMsg(this, dlist));
+}
diff --git a/gps/gnss/XtraSystemStatusObserver.h b/gps/gnss/XtraSystemStatusObserver.h
new file mode 100644
index 0000000..56a3a9c
--- /dev/null
+++ b/gps/gnss/XtraSystemStatusObserver.h
@@ -0,0 +1,112 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef XTRA_SYSTEM_STATUS_OBS_H
+#define XTRA_SYSTEM_STATUS_OBS_H
+
+#include <cinttypes>
+#include <MsgTask.h>
+#include <LocIpc.h>
+#include <LocTimer.h>
+#include <stdlib.h>
+
+using namespace std;
+using namespace loc_util;
+using loc_core::IOsObserver;
+using loc_core::IDataItemObserver;
+using loc_core::IDataItemCore;
+
+struct StartDgnssNtripParams {
+ GnssNtripConnectionParams ntripParams;
+ string nmea;
+
+ void clear() {
+ ntripParams.hostNameOrIp.clear();
+ ntripParams.mountPoint.clear();
+ ntripParams.username.clear();
+ ntripParams.password.clear();
+ ntripParams.port = 0;
+ ntripParams.useSSL = false;
+ ntripParams.requiresNmeaLocation = false;
+ nmea.clear();
+ }
+};
+
+class XtraSystemStatusObserver : public IDataItemObserver {
+public :
+ // constructor & destructor
+ XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask);
+ inline virtual ~XtraSystemStatusObserver() {
+ subscribe(false);
+ mIpc.stopNonBlockingListening();
+ }
+
+ // IDataItemObserver overrides
+ inline virtual void getName(string& name);
+ virtual void notify(const list<IDataItemCore*>& dlist);
+
+ bool updateLockStatus(GnssConfigGpsLock lock);
+ bool updateConnections(uint64_t allConnections,
+ loc_core::NetworkInfoType* networkHandleInfo);
+ bool updateTac(const string& tac);
+ bool updateMccMnc(const string& mccmnc);
+ bool updateXtraThrottle(const bool enabled);
+ inline const MsgTask* getMsgTask() { return mMsgTask; }
+ void subscribe(bool yes);
+ bool onStatusRequested(int32_t xtraStatusUpdated);
+ void startDgnssSource(const StartDgnssNtripParams& params);
+ void restartDgnssSource();
+ void stopDgnssSource();
+ void updateNmeaToDgnssServer(const string& nmea);
+
+private:
+ IOsObserver* mSystemStatusObsrvr;
+ const MsgTask* mMsgTask;
+ GnssConfigGpsLock mGpsLock;
+ LocIpc mIpc;
+ uint64_t mConnections;
+ loc_core::NetworkInfoType mNetworkHandle[MAX_NETWORK_HANDLES];
+ string mTac;
+ string mMccmnc;
+ bool mXtraThrottle;
+ bool mReqStatusReceived;
+ bool mIsConnectivityStatusKnown;
+ shared_ptr<LocIpcSender> mSender;
+ string mNtripParamsString;
+
+ class DelayLocTimer : public LocTimer {
+ LocIpcSender& mSender;
+ public:
+ DelayLocTimer(LocIpcSender& sender) : mSender(sender) {}
+ void timeOutCallback() override {
+ LocIpc::send(mSender, (const uint8_t*)"halinit", sizeof("halinit"));
+ }
+ } mDelayLocTimer;
+};
+
+#endif
diff --git a/gps/gnss/location_gnss.cpp b/gps/gnss/location_gnss.cpp
new file mode 100644
index 0000000..0454a13
--- /dev/null
+++ b/gps/gnss/location_gnss.cpp
@@ -0,0 +1,593 @@
+/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "GnssAdapter.h"
+#include "location_interface.h"
+
+static GnssAdapter* gGnssAdapter = NULL;
+
+static void initialize();
+static void deinitialize();
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks);
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+static void requestCapabilities(LocationAPI* client);
+
+static uint32_t startTracking(LocationAPI* client, TrackingOptions&);
+static void updateTrackingOptions(LocationAPI* client, uint32_t id, TrackingOptions&);
+static void stopTracking(LocationAPI* client, uint32_t id);
+
+static void gnssNiResponse(LocationAPI* client, uint32_t id, GnssNiResponse response);
+static uint32_t gnssDeleteAidingData(GnssAidingData& data);
+static void gnssUpdateXtraThrottle(const bool enabled);
+
+static void setControlCallbacks(LocationControlCallbacks& controlCallbacks);
+static uint32_t enable(LocationTechnologyType techType);
+static void disable(uint32_t id);
+static uint32_t* gnssUpdateConfig(const GnssConfig& config);
+static uint32_t* gnssGetConfig(GnssConfigFlagsMask mask);
+
+static void gnssUpdateSvTypeConfig(GnssSvTypeConfig& config);
+static void gnssGetSvTypeConfig(GnssSvTypeConfigCallback& callback);
+static void gnssResetSvTypeConfig();
+
+static void injectLocation(double latitude, double longitude, float accuracy);
+static void injectLocationExt(const GnssLocationInfoNotification &locationInfo);
+static void injectTime(int64_t time, int64_t timeReference, int32_t uncertainty);
+
+static void agpsInit(const AgpsCbInfo& cbInfo);
+static void agpsDataConnOpen(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType);
+static void agpsDataConnClosed(AGpsExtType agpsType);
+static void agpsDataConnFailed(AGpsExtType agpsType);
+static void getDebugReport(GnssDebugReport& report);
+static void updateConnectionStatus(bool connected, int8_t type, bool roaming,
+ NetworkHandle networkHandle, string& apn);
+static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb);
+static void enableNfwLocationAccess(bool enable);
+static void nfwInit(const NfwCbInfo& cbInfo);
+static void getPowerStateChanges(std::function<void(bool)> powerStateCb);
+
+static void odcpiInit(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
+static void odcpiInject(const Location& location);
+
+static void blockCPI(double latitude, double longitude, float accuracy,
+ int blockDurationMsec, double latLonDiffThreshold);
+static void updateBatteryStatus(bool charging);
+static void updateSystemPowerState(PowerStateType systemPowerState);
+static uint32_t setConstrainedTunc (bool enable, float tuncConstraint,
+ uint32_t energyBudget);
+static uint32_t setPositionAssistedClockEstimator(bool enable);
+static uint32_t gnssUpdateSvConfig(const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig);
+static uint32_t gnssResetSvConfig();
+static uint32_t configLeverArm(const LeverArmConfigInfo& configInfo);
+static uint32_t configRobustLocation(bool enable, bool enableForE911);
+static uint32_t configMinGpsWeek(uint16_t minGpsWeek);
+static uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig);
+static uint32_t gnssUpdateSecondaryBandConfig(const GnssSvTypeConfig& secondaryBandConfig);
+static uint32_t gnssGetSecondaryBandConfig();
+static void resetNetworkInfo();
+
+static void updateNTRIPGGAConsent(bool consentAccepted);
+static void enablePPENtripStream(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+static void disablePPENtripStream();
+
+static bool measCorrInit(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+static bool measCorrSetCorrections(const GnssMeasurementCorrections gnssMeasCorr);
+static void measCorrClose();
+static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback);
+static void antennaInfoClose();
+static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState);
+
+static const GnssInterface gGnssInterface = {
+ sizeof(GnssInterface),
+ initialize,
+ deinitialize,
+ addClient,
+ removeClient,
+ requestCapabilities,
+ startTracking,
+ updateTrackingOptions,
+ stopTracking,
+ gnssNiResponse,
+ setControlCallbacks,
+ enable,
+ disable,
+ gnssUpdateConfig,
+ gnssGetConfig,
+ gnssUpdateSvTypeConfig,
+ gnssGetSvTypeConfig,
+ gnssResetSvTypeConfig,
+ gnssDeleteAidingData,
+ gnssUpdateXtraThrottle,
+ injectLocation,
+ injectTime,
+ agpsInit,
+ agpsDataConnOpen,
+ agpsDataConnClosed,
+ agpsDataConnFailed,
+ getDebugReport,
+ updateConnectionStatus,
+ odcpiInit,
+ odcpiInject,
+ blockCPI,
+ getGnssEnergyConsumed,
+ enableNfwLocationAccess,
+ nfwInit,
+ getPowerStateChanges,
+ injectLocationExt,
+ updateBatteryStatus,
+ updateSystemPowerState,
+ setConstrainedTunc,
+ setPositionAssistedClockEstimator,
+ gnssUpdateSvConfig,
+ configLeverArm,
+ measCorrInit,
+ measCorrSetCorrections,
+ measCorrClose,
+ antennaInfoInit,
+ antennaInfoClose,
+ configRobustLocation,
+ configMinGpsWeek,
+ configDeadReckoningEngineParams,
+ updateNTRIPGGAConsent,
+ enablePPENtripStream,
+ disablePPENtripStream,
+ gnssUpdateSecondaryBandConfig,
+ gnssGetSecondaryBandConfig,
+ resetNetworkInfo,
+ configEngineRunState
+};
+
+#ifndef DEBUG_X86
+extern "C" const GnssInterface* getGnssInterface()
+#else
+const GnssInterface* getGnssInterface()
+#endif // DEBUG_X86
+{
+ gGnssInterface.initialize();
+ return &gGnssInterface;
+}
+
+static void initialize()
+{
+ if (NULL == gGnssAdapter) {
+ gGnssAdapter = new GnssAdapter();
+ }
+}
+
+static void deinitialize()
+{
+ if (NULL != gGnssAdapter) {
+ delete gGnssAdapter;
+ gGnssAdapter = NULL;
+ }
+}
+
+static void addClient(LocationAPI* client, const LocationCallbacks& callbacks)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->addClientCommand(client, callbacks);
+ }
+}
+
+static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->removeClientCommand(client, rmClientCb);
+ }
+}
+
+static void requestCapabilities(LocationAPI* client)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->requestCapabilitiesCommand(client);
+ }
+}
+
+static uint32_t startTracking(
+ LocationAPI* client, TrackingOptions& trackingOptions)
+{
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->startTrackingCommand(client, trackingOptions);
+ } else {
+ return 0;
+ }
+}
+
+static void updateTrackingOptions(
+ LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->updateTrackingOptionsCommand(
+ client, id, trackingOptions);
+ }
+}
+
+static void stopTracking(LocationAPI* client, uint32_t id)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->stopTrackingCommand(client, id);
+ }
+}
+
+static void gnssNiResponse(LocationAPI* client, uint32_t id, GnssNiResponse response)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->gnssNiResponseCommand(client, id, response);
+ }
+}
+
+static void setControlCallbacks(LocationControlCallbacks& controlCallbacks)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->setControlCallbacksCommand(controlCallbacks);
+ }
+}
+
+static uint32_t enable(LocationTechnologyType techType)
+{
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->enableCommand(techType);
+ } else {
+ return 0;
+ }
+}
+
+static void disable(uint32_t id)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->disableCommand(id);
+ }
+}
+
+static uint32_t* gnssUpdateConfig(const GnssConfig& config)
+{
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssUpdateConfigCommand(config);
+ } else {
+ return NULL;
+ }
+}
+
+static uint32_t* gnssGetConfig(GnssConfigFlagsMask mask)
+{
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssGetConfigCommand(mask);
+ } else {
+ return NULL;
+ }
+}
+
+static void gnssUpdateSvTypeConfig(GnssSvTypeConfig& config)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->gnssUpdateSvTypeConfigCommand(config);
+ }
+}
+
+static void gnssGetSvTypeConfig(GnssSvTypeConfigCallback& callback)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->gnssGetSvTypeConfigCommand(callback);
+ }
+}
+
+static void gnssResetSvTypeConfig()
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->gnssResetSvTypeConfigCommand();
+ }
+}
+
+static uint32_t gnssDeleteAidingData(GnssAidingData& data)
+{
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssDeleteAidingDataCommand(data);
+ } else {
+ return 0;
+ }
+}
+
+static void gnssUpdateXtraThrottle(const bool enabled)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->gnssUpdateXtraThrottleCommand(enabled);
+ }
+}
+
+static void injectLocation(double latitude, double longitude, float accuracy)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->injectLocationCommand(latitude, longitude, accuracy);
+ }
+}
+
+static void injectTime(int64_t time, int64_t timeReference, int32_t uncertainty)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->injectTimeCommand(time, timeReference, uncertainty);
+ }
+}
+
+static void agpsInit(const AgpsCbInfo& cbInfo) {
+
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->initAgpsCommand(cbInfo);
+ }
+}
+static void agpsDataConnOpen(
+ AGpsExtType agpsType, const char* apnName, int apnLen, int ipType) {
+
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->dataConnOpenCommand(
+ agpsType, apnName, apnLen, (AGpsBearerType)ipType);
+ }
+}
+static void agpsDataConnClosed(AGpsExtType agpsType) {
+
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->dataConnClosedCommand(agpsType);
+ }
+}
+static void agpsDataConnFailed(AGpsExtType agpsType) {
+
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->dataConnFailedCommand(agpsType);
+ }
+}
+
+static void getDebugReport(GnssDebugReport& report) {
+
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getDebugReport(report);
+ }
+}
+
+static void updateConnectionStatus(bool connected, int8_t type,
+ bool roaming, NetworkHandle networkHandle,
+ string& apn) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getSystemStatus()->eventConnectionStatus(
+ connected, type, roaming, networkHandle, apn);
+ }
+}
+
+static void odcpiInit(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->initOdcpiCommand(callback, priority);
+ }
+}
+
+static void odcpiInject(const Location& location)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->injectOdcpiCommand(location);
+ }
+}
+
+static void blockCPI(double latitude, double longitude, float accuracy,
+ int blockDurationMsec, double latLonDiffThreshold) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->blockCPICommand(latitude, longitude, accuracy,
+ blockDurationMsec, latLonDiffThreshold);
+ }
+}
+
+static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getGnssEnergyConsumedCommand(energyConsumedCb);
+ }
+}
+
+static void enableNfwLocationAccess(bool enable) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->nfwControlCommand(enable);
+ }
+}
+
+static void nfwInit(const NfwCbInfo& cbInfo) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->initNfwCommand(cbInfo);
+ }
+}
+
+static void getPowerStateChanges(std::function<void(bool)> powerStateCb)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getPowerStateChangesCommand(powerStateCb);
+ }
+}
+
+static void injectLocationExt(const GnssLocationInfoNotification &locationInfo)
+{
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->injectLocationExtCommand(locationInfo);
+ }
+}
+
+static void updateBatteryStatus(bool charging) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getSystemStatus()->updatePowerConnectState(charging);
+ }
+}
+
+static void resetNetworkInfo() {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->getSystemStatus()->resetNetworkInfo();
+ }
+}
+
+static void updateSystemPowerState(PowerStateType systemPowerState) {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->updateSystemPowerStateCommand(systemPowerState);
+ }
+}
+
+static uint32_t setConstrainedTunc (bool enable, float tuncConstraint, uint32_t energyBudget) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->setConstrainedTuncCommand(enable, tuncConstraint, energyBudget);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t setPositionAssistedClockEstimator(bool enable) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->setPositionAssistedClockEstimatorCommand(enable);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t gnssUpdateSvConfig(
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssUpdateSvConfigCommand(
+ constellationEnablementConfig, blacklistSvConfig);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t configLeverArm(const LeverArmConfigInfo& configInfo){
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->configLeverArmCommand(configInfo);
+ } else {
+ return 0;
+ }
+}
+
+static bool measCorrInit(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->openMeasCorrCommand(setCapabilitiesCb);
+ } else {
+ return false;
+ }
+}
+
+static bool measCorrSetCorrections(const GnssMeasurementCorrections gnssMeasCorr) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->measCorrSetCorrectionsCommand(gnssMeasCorr);
+ } else {
+ return false;
+ }
+}
+
+static void measCorrClose() {
+ if (NULL != gGnssAdapter) {
+ gGnssAdapter->closeMeasCorrCommand();
+ }
+}
+
+static uint32_t antennaInfoInit(const antennaInfoCb antennaInfoCallback) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->antennaInfoInitCommand(antennaInfoCallback);
+ } else {
+ return ANTENNA_INFO_ERROR_GENERIC;
+ }
+}
+
+static void antennaInfoClose() {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->antennaInfoCloseCommand();
+ }
+}
+
+static uint32_t configRobustLocation(bool enable, bool enableForE911){
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->configRobustLocationCommand(enable, enableForE911);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t configMinGpsWeek(uint16_t minGpsWeek){
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->configMinGpsWeekCommand(minGpsWeek);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig){
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->configDeadReckoningEngineParamsCommand(dreConfig);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t gnssUpdateSecondaryBandConfig(
+ const GnssSvTypeConfig& secondaryBandConfig) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssUpdateSecondaryBandConfigCommand(secondaryBandConfig);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t gnssGetSecondaryBandConfig(){
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->gnssGetSecondaryBandConfigCommand();
+ } else {
+ return 0;
+ }
+}
+
+static void updateNTRIPGGAConsent(bool consentAccepted){
+ if (NULL != gGnssAdapter) {
+ // Call will be enabled once GnssAdapter impl. is ready.
+ gGnssAdapter->updateNTRIPGGAConsentCommand(consentAccepted);
+ }
+}
+
+static void enablePPENtripStream(const GnssNtripConnectionParams& params, bool enableRTKEngine){
+ if (NULL != gGnssAdapter) {
+ // Call will be enabled once GnssAdapter impl. is ready.
+ gGnssAdapter->enablePPENtripStreamCommand(params, enableRTKEngine);
+ }
+}
+
+static void disablePPENtripStream(){
+ if (NULL != gGnssAdapter) {
+ // Call will be enabled once GnssAdapter impl. is ready.
+ gGnssAdapter->disablePPENtripStreamCommand();
+ }
+}
+
+static uint32_t configEngineRunState(PositioningEngineMask engType, LocEngineRunState engState) {
+ if (NULL != gGnssAdapter) {
+ return gGnssAdapter->configEngineRunStateCommand(engType, engState);
+ } else {
+ return 0;
+ }
+}
diff --git a/gps/gps_vendor_board.mk b/gps/gps_vendor_board.mk
new file mode 100644
index 0000000..e1915ea
--- /dev/null
+++ b/gps/gps_vendor_board.mk
@@ -0,0 +1,7 @@
+# Flags from BoardConfigVendor.mk
+ifneq ($(TARGET_USES_QMAA),true)
+BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default
+else ifneq ($(TARGET_USES_QMAA_OVERRIDE_GPS),false)
+BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default
+endif
+
diff --git a/gps/gps_vendor_product.mk b/gps/gps_vendor_product.mk
new file mode 100644
index 0000000..0e578e8
--- /dev/null
+++ b/gps/gps_vendor_product.mk
@@ -0,0 +1,44 @@
+# HAL packages
+ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
+
+# GPS-HIDL
+LOC_BOARD_PLATFORM_LIST += msm8937
+LOC_BOARD_PLATFORM_LIST += msm8953
+LOC_BOARD_PLATFORM_LIST += msm8998
+LOC_BOARD_PLATFORM_LIST += apq8098_latv
+LOC_BOARD_PLATFORM_LIST += sdm710
+LOC_BOARD_PLATFORM_LIST += qcs605
+LOC_BOARD_PLATFORM_LIST += sdm845
+LOC_BOARD_PLATFORM_LIST += sdm660
+LOC_BOARD_PLATFORM_LIST += msmnile
+LOC_BOARD_PLATFORM_LIST += sdmshrike
+LOC_BOARD_PLATFORM_LIST += $(MSMSTEPPE)
+LOC_BOARD_PLATFORM_LIST += $(TRINKET)
+LOC_BOARD_PLATFORM_LIST += kona
+LOC_BOARD_PLATFORM_LIST += atoll
+LOC_BOARD_PLATFORM_LIST += lito
+LOC_BOARD_PLATFORM_LIST += bengal
+LOC_BOARD_PLATFORM_LIST += lahaina
+LOC_BOARD_PLATFORM_LIST += holi
+
+# Add product packages
+ifneq (,$(filter $(LOC_BOARD_PLATFORM_LIST),$(TARGET_BOARD_PLATFORM)))
+
+PRODUCT_PACKAGES += gps.conf
+PRODUCT_PACKAGES += flp.conf
+PRODUCT_PACKAGES += gnss_antenna_info.conf
+PRODUCT_PACKAGES += libloc_pla_headers
+PRODUCT_PACKAGES += liblocation_api_headers
+PRODUCT_PACKAGES += libgps.utils_headers
+PRODUCT_PACKAGES += liblocation_api
+PRODUCT_PACKAGES += libgps.utils
+PRODUCT_PACKAGES += libbatching
+PRODUCT_PACKAGES += libgeofencing
+PRODUCT_PACKAGES += libloc_core
+PRODUCT_PACKAGES += libgnss
+
+PRODUCT_PACKAGES += android.hardware.gnss@2.1-impl-qti
+PRODUCT_PACKAGES += android.hardware.gnss@2.1-service-qti
+
+endif # ifneq (,$(filter $(LOC_BOARD_PLATFORM_LIST),$(TARGET_BOARD_PLATFORM)))
+endif # ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
diff --git a/gps/loc-hal.pc.in b/gps/loc-hal.pc.in
new file mode 100644
index 0000000..22d174b
--- /dev/null
+++ b/gps/loc-hal.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: loc-hal
+Description: QTI GPS Loc HAL
+Version: @VERSION
+Libs: -L${libdir} -lgnss
+Cflags: -I${includedir} -I${includedir}/utils -I${includedir}/core -I${includedir}/loc-hal
diff --git a/gps/location/Android.bp b/gps/location/Android.bp
new file mode 100644
index 0000000..8532a08
--- /dev/null
+++ b/gps/location/Android.bp
@@ -0,0 +1,36 @@
+
+cc_library_shared {
+
+ name: "liblocation_api",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ shared_libs: [
+ "libutils",
+ "libcutils",
+ "libgps.utils",
+ "libdl",
+ "liblog",
+ ],
+
+ srcs: [
+ "LocationAPI.cpp",
+ "LocationAPIClientBase.cpp",
+ ],
+
+ cflags: ["-fno-short-enums"] + GNSS_CFLAGS,
+
+ header_libs: [
+ "libloc_pla_headers",
+ "libgps.utils_headers",
+ ],
+
+}
+
+cc_library_headers {
+
+ name: "liblocation_api_headers",
+ export_include_dirs: ["."],
+ vendor: true,
+}
diff --git a/gps/location/ILocationAPI.h b/gps/location/ILocationAPI.h
new file mode 100644
index 0000000..29846ac
--- /dev/null
+++ b/gps/location/ILocationAPI.h
@@ -0,0 +1,406 @@
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ILOCATIONAPI_H
+#define ILOCATIONAPI_H
+
+#include "LocationDataTypes.h"
+
+class ILocationAPI
+{
+public:
+ virtual ~ILocationAPI(){};
+
+ /** @brief Updates/changes the callbacks that will be called.
+ mandatory callbacks must be present for callbacks to be successfully updated
+ no return value */
+ virtual void updateCallbacks(LocationCallbacks&) = 0;
+
+ /* ================================== TRACKING ================================== */
+
+ /** @brief Starts a tracking session, which returns a session id that will be
+ used by the other tracking APIs and also in the responseCallback to match command
+ with response. locations are reported on the registered trackingCallback
+ periodically according to LocationOptions.
+ @return session id
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successfully started
+ LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress
+ LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed
+ LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameter is invalid */
+ virtual uint32_t startTracking(TrackingOptions&) = 0;
+
+ /** @brief Stops a tracking session associated with id parameter.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
+ virtual void stopTracking(uint32_t id) = 0;
+
+ /** @brief Changes the LocationOptions of a tracking session associated with id.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
+ virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) = 0;
+
+ /* ================================== BATCHING ================================== */
+
+ /** @brief starts a batching session, which returns a session id that will be
+ used by the other batching APIs and also in the responseCallback to match command
+ with response. locations are reported on the batchingCallback passed in createInstance
+ periodically according to LocationOptions. A batching session starts tracking on
+ the low power processor and delivers them in batches by the batchingCallback when
+ the batch is full or when getBatchedLocations is called. This allows for the processor
+ that calls this API to sleep when the low power processor can batch locations in the
+ backgroup and wake up the processor calling the API only when the batch is full, thus
+ saving power.
+ @return session id
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress
+ LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback
+ LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid
+ LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */
+ virtual uint32_t startBatching(BatchingOptions&) = 0;
+
+ /** @brief Stops a batching session associated with id parameter.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */
+ virtual void stopBatching(uint32_t id) = 0;
+
+ /** @brief Changes the LocationOptions of a batching session associated with id.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
+ virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) = 0;
+
+ /** @brief Gets a number of locations that are currently stored/batched
+ on the low power processor, delivered by the batchingCallback passed in createInstance.
+ Location are then deleted from the batch stored on the low power processor.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call
+ LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
+ virtual void getBatchedLocations(uint32_t id, size_t count) = 0;
+
+ /* ================================== GEOFENCE ================================== */
+
+ /** @brief Adds any number of geofences and returns an array of geofence ids that
+ will be used by the other geofence APIs and also in the collectiveResponseCallback to
+ match command with response. The geofenceBreachCallback will deliver the status of each
+ geofence according to the GeofenceOption for each. The geofence id array returned will
+ be valid until the collectiveResponseCallback is called and has returned.
+ @return id array
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */
+ virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) = 0;
+
+ /** @brief Removes any number of geofences. Caller should delete ids array after
+ removeGeofences returneds.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void removeGeofences(size_t count, uint32_t* ids) = 0;
+
+ /** @brief Modifies any number of geofences. Caller should delete ids array after
+ modifyGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */
+ virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) = 0;
+
+ /** @brief Pauses any number of geofences, which is similar to removeGeofences,
+ only that they can be resumed at any time. Caller should delete ids array after
+ pauseGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void pauseGeofences(size_t count, uint32_t* ids) = 0;
+
+ /** @brief Resumes any number of geofences that are currently paused. Caller should
+ delete ids array after resumeGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void resumeGeofences(size_t count, uint32_t* ids) = 0;
+
+ /* ================================== GNSS ====================================== */
+
+ /** @brief gnssNiResponse is called in response to a gnssNiCallback.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */
+ virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) = 0;
+};
+
+class ILocationControlAPI
+{
+public:
+ virtual ~ILocationControlAPI(){};
+
+ /** @brief Updates the gnss specific configuration, which returns a session id array
+ with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits.
+ The response for each config that is set will be returned in collectiveResponseCallback.
+ The session id array returned will be valid until the collectiveResponseCallback is called
+ and has returned. This effect is global for all clients of ILocationAPI.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
+ LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
+ virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) = 0;
+
+ /** @brief Delete specific gnss aiding data for testing, which returns a session id
+ that will be returned in responseCallback to match command with response.
+ Only allowed in userdebug builds. This effect is global for all clients of ILocationAPI.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */
+ virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) = 0;
+
+ /** @brief
+ Configure the constellation and SVs to be used by the GNSS engine on
+ modem.
+
+ @param
+ constellationEnablementConfig: configuration to enable/disable SV
+ constellation to be used by SPE engine. When size in
+ constellationEnablementConfig is set to 0, this indicates to reset SV
+ constellation configuration to modem NV default.
+
+ blacklistSvConfig: configuration to blacklist or unblacklist SVs
+ used by SPE engine
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configConstellations(
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) = 0;
+
+ /** @brief
+ Configure the secondary band of constellations to be used by
+ the GNSS engine on modem.
+
+ @param
+ secondaryBandConfig: configuration the secondary band usage
+ for SPE engine
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configConstellationSecondaryBand(
+ const GnssSvTypeConfig& secondaryBandConfig) = 0;
+
+ /** @brief
+ Enable or disable the constrained time uncertainty feature.
+
+ @param
+ enable: true to enable the constrained time uncertainty
+ feature and false to disable the constrainted time
+ uncertainty feature.
+
+ @param
+ tuncThreshold: this specifies the time uncertainty threshold
+ that gps engine need to maintain, in units of milli-seconds.
+ Default is 0.0 meaning that modem default value of time
+ uncertainty threshold will be used. This parameter is
+ ignored when requesting to disable this feature.
+
+ @param
+ energyBudget: this specifies the power budget that gps
+ engine is allowed to spend to maintain the time uncertainty.
+ Default is 0 meaning that GPS engine is not constained by
+ power budget and can spend as much power as needed. The
+ parameter need to be specified in units of 0.1 milli watt
+ second. This parameter is ignored requesting to disable this
+ feature.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters
+ are invalid
+ */
+ virtual uint32_t configConstrainedTimeUncertainty(
+ bool enable, float tuncThreshold = 0.0,
+ uint32_t energyBudget = 0) = 0;
+
+ /** @brief
+ Enable or disable position assisted clock estimator feature.
+
+ @param
+ enable: true to enable position assisted clock estimator and
+ false to disable the position assisted clock estimator
+ feature.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configPositionAssistedClockEstimator(bool enable) = 0;
+
+ /** @brief
+ Sets the lever arm parameters for the vehicle.
+
+ @param
+ configInfo: lever arm configuration info regarding below two
+ types of lever arm info:
+ a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial
+ measurement unit.
+ b: lever arm parameters regarding the OPF (output frame)
+ w.r.t the origin (at the GPS Antenna). Vehicle manufacturers
+ prefer the position output to be tied to a specific point in
+ the vehicle rather than where the antenna is placed
+ (midpoint of the rear axle is typical).
+
+ Caller can choose types of lever arm info to configure via the
+ leverMarkTypeMask.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) = 0;
+
+ /** @brief
+ Configure the robust location setting.
+
+ @param
+ enable: true to enable robust location and false to disable
+ robust location.
+
+ @param
+ enableForE911: true to enable robust location when device is on
+ E911 session and false to disable on E911 session.
+ This parameter is only valid if robust location is enabled.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configRobustLocation(bool enable, bool enableForE911) = 0;
+
+ /** @brief
+ Config the minimum GPS week used by modem GNSS engine.
+
+ @param
+ minGpsWeek: minimum GPS week to be used by modem GNSS engine.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) = 0;
+
+ /** @brief
+ Configure the vehicle body-to-Sensor mount parameters and
+ other parameters for dead reckoning position engine.
+
+ @param
+ dreConfig: vehicle body-to-Sensor mount angles and other
+ parameters.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig)=0;
+
+ /** @brief
+ This API is used to instruct the specified engine to be in
+ the pause/resume state. <br/>
+
+ When the engine is placed in paused state, the engine will
+ stop. If there is an on-going session, engine will no longer
+ produce fixes. In the paused state, calling API to delete
+ aiding data from the paused engine may not have effect.
+ Request to delete Aiding data shall be issued after
+ engine resume. <br/>
+
+ Currently, only DRE engine will support pause/resume
+ request. responseCb() will return not supported when request
+ is made to pause/resume none-DRE engine. <br/>
+
+ Request to pause/resume DRE engine can be made with or
+ without an on-going session. With QDR engine, on resume,
+ GNSS position & heading re-acquisition is needed for DR
+ engine to engage. If DR engine is already in the requested
+ state, the request will be no-op. <br/>
+
+ @param
+ engType: the engine that is instructed to change its run
+ state. <br/>
+
+ engState: the new engine run state that the engine is
+ instructed to be in. <br/>
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configEngineRunState(PositioningEngineMask engType,
+ LocEngineRunState engState) = 0;
+};
+
+#endif /* ILOCATIONAPI_H */
diff --git a/gps/location/LocationAPI.cpp b/gps/location/LocationAPI.cpp
new file mode 100644
index 0000000..3a50c46
--- /dev/null
+++ b/gps/location/LocationAPI.cpp
@@ -0,0 +1,976 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_LocationAPI"
+
+#include <location_interface.h>
+#include <dlfcn.h>
+#include <loc_pla.h>
+#include <log_util.h>
+#include <pthread.h>
+#include <map>
+#include <loc_misc_utils.h>
+
+typedef const GnssInterface* (getGnssInterface)();
+typedef const GeofenceInterface* (getGeofenceInterface)();
+typedef const BatchingInterface* (getBatchingInterface)();
+typedef void (createOSFramework)();
+typedef void (destroyOSFramework)();
+
+// GTP services
+typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback);
+typedef void (enableProviderGetter)();
+typedef void (disableProviderGetter)();
+typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback);
+typedef void (stopNetworkLocationGetter)(trackingCallback* callback);
+
+typedef struct {
+ // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
+ // before we invoke the registered locationApiDestroyCompleteCallback
+ LocationAdapterTypeMask waitAdapterMask;
+ locationApiDestroyCompleteCallback destroyCompleteCb;
+} LocationAPIDestroyCbData;
+
+// This is the map for the client that has requested destroy with
+// destroy callback provided.
+typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
+ LocationClientDestroyCbMap;
+
+typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
+typedef struct {
+ LocationClientMap clientData;
+ LocationClientDestroyCbMap destroyClientData;
+ LocationControlAPI* controlAPI;
+ LocationControlCallbacks controlCallbacks;
+ GnssInterface* gnssInterface;
+ GeofenceInterface* geofenceInterface;
+ BatchingInterface* batchingInterface;
+} LocationAPIData;
+
+static LocationAPIData gData = {};
+static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gGnssLoadFailed = false;
+static bool gBatchingLoadFailed = false;
+static bool gGeofenceLoadFailed = false;
+static uint32_t gOSFrameworkRefCount = 0;
+
+template <typename T1, typename T2>
+static const T1* loadLocationInterface(const char* library, const char* name) {
+ void* libhandle = nullptr;
+ T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name);
+ if (nullptr == getter) {
+ return (const T1*) getter;
+ }else {
+ return (*getter)();
+ }
+}
+
+static void createOSFrameworkInstance() {
+ void* libHandle = nullptr;
+ createOSFramework* getter = (createOSFramework*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "createOSFramework");
+ if (getter != nullptr) {
+ (*getter)();
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+static void destroyOSFrameworkInstance() {
+ void* libHandle = nullptr;
+ destroyOSFramework* getter = (destroyOSFramework*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "destroyOSFramework");
+ if (getter != nullptr) {
+ (*getter)();
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.gnssLocationInfoCb != nullptr ||
+ locationCallbacks.engineLocationsInfoCb != nullptr ||
+ locationCallbacks.gnssSvCb != nullptr ||
+ locationCallbacks.gnssNmeaCb != nullptr ||
+ locationCallbacks.gnssDataCb != nullptr ||
+ locationCallbacks.gnssMeasurementsCb != nullptr);
+}
+
+static bool isGnssClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.gnssNiCb != nullptr ||
+ locationCallbacks.trackingCb != nullptr ||
+ locationCallbacks.gnssLocationInfoCb != nullptr ||
+ locationCallbacks.engineLocationsInfoCb != nullptr ||
+ locationCallbacks.gnssSvCb != nullptr ||
+ locationCallbacks.gnssNmeaCb != nullptr ||
+ locationCallbacks.gnssDataCb != nullptr ||
+ locationCallbacks.gnssMeasurementsCb != nullptr ||
+ locationCallbacks.locationSystemInfoCb != nullptr);
+}
+
+static bool isBatchingClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.batchingCb != nullptr);
+}
+
+static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
+{
+ return (locationCallbacks.geofenceBreachCb != nullptr ||
+ locationCallbacks.geofenceStatusCb != nullptr);
+}
+
+
+void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType)
+{
+ bool invokeCallback = false;
+ locationApiDestroyCompleteCallback destroyCompleteCb;
+ LOC_LOGd("adatper type %x", adapterType);
+ pthread_mutex_lock(&gDataMutex);
+ auto it = gData.destroyClientData.find(this);
+ if (it != gData.destroyClientData.end()) {
+ it->second.waitAdapterMask &= ~adapterType;
+ if (it->second.waitAdapterMask == 0) {
+ invokeCallback = true;
+ destroyCompleteCb = it->second.destroyCompleteCb;
+ gData.destroyClientData.erase(it);
+ }
+ }
+ pthread_mutex_unlock(&gDataMutex);
+
+ if (invokeCallback) {
+ LOC_LOGd("invoke client destroy cb");
+ if (!destroyCompleteCb) {
+ (destroyCompleteCb) ();
+ }
+
+ delete this;
+ }
+}
+
+void onGnssRemoveClientCompleteCb (LocationAPI* client)
+{
+ client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT);
+}
+
+void onBatchingRemoveClientCompleteCb (LocationAPI* client)
+{
+ client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT);
+}
+
+void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
+{
+ client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
+}
+
+LocationAPI*
+LocationAPI::createInstance (LocationCallbacks& locationCallbacks)
+{
+ if (nullptr == locationCallbacks.capabilitiesCb ||
+ nullptr == locationCallbacks.responseCb ||
+ nullptr == locationCallbacks.collectiveResponseCb) {
+ LOC_LOGe("missing mandatory callback, return null");
+ return NULL;
+ }
+
+ LocationAPI* newLocationAPI = new LocationAPI();
+ bool requestedCapabilities = false;
+
+ pthread_mutex_lock(&gDataMutex);
+
+ gOSFrameworkRefCount++;
+ if (1 == gOSFrameworkRefCount) {
+ createOSFrameworkInstance();
+ }
+
+ if (isGnssClient(locationCallbacks)) {
+ if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
+ gData.gnssInterface =
+ (GnssInterface*)loadLocationInterface<GnssInterface,
+ getGnssInterface>("libgnss.so", "getGnssInterface");
+ if (NULL == gData.gnssInterface) {
+ gGnssLoadFailed = true;
+ LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
+ } else {
+ gData.gnssInterface->initialize();
+ }
+ }
+ if (NULL != gData.gnssInterface) {
+ gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
+ if (!requestedCapabilities) {
+ gData.gnssInterface->requestCapabilities(newLocationAPI);
+ requestedCapabilities = true;
+ }
+ }
+ }
+
+ if (isBatchingClient(locationCallbacks)) {
+ if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
+ gData.batchingInterface =
+ (BatchingInterface*)loadLocationInterface<BatchingInterface,
+ getBatchingInterface>("libbatching.so", "getBatchingInterface");
+ if (NULL == gData.batchingInterface) {
+ gBatchingLoadFailed = true;
+ LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
+ } else {
+ gData.batchingInterface->initialize();
+ }
+ }
+ if (NULL != gData.batchingInterface) {
+ gData.batchingInterface->addClient(newLocationAPI, locationCallbacks);
+ if (!requestedCapabilities) {
+ gData.batchingInterface->requestCapabilities(newLocationAPI);
+ requestedCapabilities = true;
+ }
+ }
+ }
+
+ if (isGeofenceClient(locationCallbacks)) {
+ if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
+ gData.geofenceInterface =
+ (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
+ getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
+ if (NULL == gData.geofenceInterface) {
+ gGeofenceLoadFailed = true;
+ LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
+ } else {
+ gData.geofenceInterface->initialize();
+ }
+ }
+ if (NULL != gData.geofenceInterface) {
+ gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks);
+ if (!requestedCapabilities) {
+ gData.geofenceInterface->requestCapabilities(newLocationAPI);
+ requestedCapabilities = true;
+ }
+ }
+ }
+
+ gData.clientData[newLocationAPI] = locationCallbacks;
+
+ pthread_mutex_unlock(&gDataMutex);
+
+ return newLocationAPI;
+}
+
+void
+LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
+{
+ bool invokeDestroyCb = false;
+
+ pthread_mutex_lock(&gDataMutex);
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ bool removeFromGnssInf = (NULL != gData.gnssInterface);
+ bool removeFromBatchingInf = (NULL != gData.batchingInterface);
+ bool removeFromGeofenceInf = (NULL != gData.geofenceInterface);
+ bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
+ LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
+ "needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
+ needToWait);
+
+ if ((NULL != destroyCompleteCb) && (true == needToWait)) {
+ LocationAPIDestroyCbData destroyCbData = {};
+ destroyCbData.destroyCompleteCb = destroyCompleteCb;
+ // record down from which adapter we need to wait for the destroy complete callback
+ // only when we have received all the needed callbacks from all the associated stacks,
+ // we shall notify the client.
+ destroyCbData.waitAdapterMask =
+ (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
+ destroyCbData.waitAdapterMask |=
+ (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0);
+ destroyCbData.waitAdapterMask |=
+ (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
+ gData.destroyClientData[this] = destroyCbData;
+ LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
+ }
+
+ if (removeFromGnssInf) {
+ gData.gnssInterface->removeClient(it->first,
+ onGnssRemoveClientCompleteCb);
+ }
+ if (removeFromBatchingInf) {
+ gData.batchingInterface->removeClient(it->first,
+ onBatchingRemoveClientCompleteCb);
+ }
+ if (removeFromGeofenceInf) {
+ gData.geofenceInterface->removeClient(it->first,
+ onGeofenceRemoveClientCompleteCb);
+ }
+
+ gData.clientData.erase(it);
+
+ if (!needToWait) {
+ invokeDestroyCb = true;
+ }
+ } else {
+ LOC_LOGE("%s:%d]: Location API client %p not found in client data",
+ __func__, __LINE__, this);
+ }
+
+ if (1 == gOSFrameworkRefCount) {
+ destroyOSFrameworkInstance();
+ }
+ gOSFrameworkRefCount--;
+
+ pthread_mutex_unlock(&gDataMutex);
+ if (invokeDestroyCb) {
+ if (!destroyCompleteCb) {
+ (destroyCompleteCb) ();
+ }
+ delete this;
+ }
+}
+
+LocationAPI::LocationAPI()
+{
+ LOC_LOGD("LOCATION API CONSTRUCTOR");
+}
+
+// private destructor
+LocationAPI::~LocationAPI()
+{
+ LOC_LOGD("LOCATION API DESTRUCTOR");
+}
+
+void
+LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
+{
+ if (nullptr == locationCallbacks.capabilitiesCb ||
+ nullptr == locationCallbacks.responseCb ||
+ nullptr == locationCallbacks.collectiveResponseCb) {
+ return;
+ }
+
+ pthread_mutex_lock(&gDataMutex);
+
+ if (isGnssClient(locationCallbacks)) {
+ if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
+ gData.gnssInterface =
+ (GnssInterface*)loadLocationInterface<GnssInterface,
+ getGnssInterface>("libgnss.so", "getGnssInterface");
+ if (NULL == gData.gnssInterface) {
+ gGnssLoadFailed = true;
+ LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
+ } else {
+ gData.gnssInterface->initialize();
+ }
+ }
+ if (NULL != gData.gnssInterface) {
+ // either adds new Client or updates existing Client
+ gData.gnssInterface->addClient(this, locationCallbacks);
+ }
+ }
+
+ if (isBatchingClient(locationCallbacks)) {
+ if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
+ gData.batchingInterface =
+ (BatchingInterface*)loadLocationInterface<BatchingInterface,
+ getBatchingInterface>("libbatching.so", "getBatchingInterface");
+ if (NULL == gData.batchingInterface) {
+ gBatchingLoadFailed = true;
+ LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
+ } else {
+ gData.batchingInterface->initialize();
+ }
+ }
+ if (NULL != gData.batchingInterface) {
+ // either adds new Client or updates existing Client
+ gData.batchingInterface->addClient(this, locationCallbacks);
+ }
+ }
+
+ if (isGeofenceClient(locationCallbacks)) {
+ if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
+ gData.geofenceInterface =
+ (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
+ getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
+ if (NULL == gData.geofenceInterface) {
+ gGeofenceLoadFailed = true;
+ LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
+ } else {
+ gData.geofenceInterface->initialize();
+ }
+ }
+ if (NULL != gData.geofenceInterface) {
+ // either adds new Client or updates existing Client
+ gData.geofenceInterface->addClient(this, locationCallbacks);
+ }
+ }
+
+ gData.clientData[this] = locationCallbacks;
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+uint32_t
+LocationAPI::startTracking(TrackingOptions& trackingOptions)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ if (NULL != gData.gnssInterface) {
+ id = gData.gnssInterface->startTracking(this, trackingOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+ } else {
+ LOC_LOGE("%s:%d]: Location API client %p not found in client data",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+void
+LocationAPI::stopTracking(uint32_t id)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->stopTracking(this, id);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+ } else {
+ LOC_LOGE("%s:%d]: Location API client %p not found in client data",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::updateTrackingOptions(
+ uint32_t id, TrackingOptions& trackingOptions)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ auto it = gData.clientData.find(this);
+ if (it != gData.clientData.end()) {
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+ } else {
+ LOC_LOGE("%s:%d]: Location API client %p not found in client data",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+uint32_t
+LocationAPI::startBatching(BatchingOptions &batchingOptions)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (NULL != gData.batchingInterface) {
+ id = gData.batchingInterface->startBatching(this, batchingOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+void
+LocationAPI::stopBatching(uint32_t id)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (NULL != gData.batchingInterface) {
+ gData.batchingInterface->stopBatching(this, id);
+ } else {
+ LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (NULL != gData.batchingInterface) {
+ gData.batchingInterface->updateBatchingOptions(this, id, batchOptions);
+ } else {
+ LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::getBatchedLocations(uint32_t id, size_t count)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.batchingInterface != NULL) {
+ gData.batchingInterface->getBatchedLocations(this, id, count);
+ } else {
+ LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+uint32_t*
+LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
+{
+ uint32_t* ids = NULL;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.geofenceInterface != NULL) {
+ ids = gData.geofenceInterface->addGeofences(this, count, options, info);
+ } else {
+ LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return ids;
+}
+
+void
+LocationAPI::removeGeofences(size_t count, uint32_t* ids)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.geofenceInterface != NULL) {
+ gData.geofenceInterface->removeGeofences(this, count, ids);
+ } else {
+ LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.geofenceInterface != NULL) {
+ gData.geofenceInterface->modifyGeofences(this, count, ids, options);
+ } else {
+ LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.geofenceInterface != NULL) {
+ gData.geofenceInterface->pauseGeofences(this, count, ids);
+ } else {
+ LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.geofenceInterface != NULL) {
+ gData.geofenceInterface->resumeGeofences(this, count, ids);
+ } else {
+ LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void
+LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->gnssNiResponse(this, id, response);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+void LocationAPI::enableNetworkProvider() {
+ void* libHandle = nullptr;
+ enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "enableNetworkProvider");
+ if (setter != nullptr) {
+ (*setter)();
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+void LocationAPI::disableNetworkProvider() {
+ void* libHandle = nullptr;
+ disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "disableNetworkProvider");
+ if (setter != nullptr) {
+ (*setter)();
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+void LocationAPI::startNetworkLocation(trackingCallback* callback) {
+ void* libHandle = nullptr;
+ getSingleNetworkLocationGetter* setter =
+ (getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "startNetworkLocation");
+ if (setter != nullptr) {
+ (*setter)(callback);
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+void LocationAPI::stopNetworkLocation(trackingCallback* callback) {
+ void* libHandle = nullptr;
+ stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "stopNetworkLocation");
+ if (setter != nullptr) {
+ LOC_LOGe("called");
+ (*setter)(callback);
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+}
+
+LocationControlAPI*
+LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
+{
+ LocationControlAPI* controlAPI = NULL;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
+ if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
+ gData.gnssInterface =
+ (GnssInterface*)loadLocationInterface<GnssInterface,
+ getGnssInterface>("libgnss.so", "getGnssInterface");
+ if (NULL == gData.gnssInterface) {
+ gGnssLoadFailed = true;
+ LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
+ } else {
+ gData.gnssInterface->initialize();
+ }
+ }
+ if (NULL != gData.gnssInterface) {
+ gData.controlAPI = new LocationControlAPI();
+ gData.controlCallbacks = locationControlCallbacks;
+ gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
+ controlAPI = gData.controlAPI;
+ }
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return controlAPI;
+}
+
+void
+LocationControlAPI::destroy()
+{
+ delete this;
+}
+
+LocationControlAPI::LocationControlAPI()
+{
+ LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
+}
+
+LocationControlAPI::~LocationControlAPI()
+{
+ LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
+ pthread_mutex_lock(&gDataMutex);
+
+ gData.controlAPI = NULL;
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+uint32_t
+LocationControlAPI::enable(LocationTechnologyType techType)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->enable(techType);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+void
+LocationControlAPI::disable(uint32_t id)
+{
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ gData.gnssInterface->disable(id);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+}
+
+uint32_t*
+LocationControlAPI::gnssUpdateConfig(const GnssConfig& config)
+{
+ uint32_t* ids = NULL;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ ids = gData.gnssInterface->gnssUpdateConfig(config);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return ids;
+}
+
+uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) {
+
+ uint32_t* ids = NULL;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (NULL != gData.gnssInterface) {
+ ids = gData.gnssInterface->gnssGetConfig(mask);
+ } else {
+ LOC_LOGe("No gnss interface available for Control API client %p", this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return ids;
+}
+
+uint32_t
+LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
+{
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->gnssDeleteAidingData(data);
+ } else {
+ LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
+ __func__, __LINE__, this);
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configConstellations(
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->gnssUpdateSvConfig(
+ constellationEnablementConfig, blacklistSvConfig);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configConstellationSecondaryBand(
+ const GnssSvTypeConfig& secondaryBandConfig) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->gnssUpdateSecondaryBandConfig(secondaryBandConfig);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configConstrainedTimeUncertainty(
+ bool enable, float tuncThreshold, uint32_t energyBudget) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->setConstrainedTunc(enable,
+ tuncThreshold,
+ energyBudget);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->setPositionAssistedClockEstimator(enable);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->configLeverArm(configInfo);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configRobustLocation(bool enable, bool enableForE911) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->configRobustLocation(enable, enableForE911);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configMinGpsWeek(uint16_t minGpsWeek) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->configMinGpsWeek(minGpsWeek);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configDeadReckoningEngineParams(
+ const DeadReckoningEngineConfig& dreConfig) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->configDeadReckoningEngineParams(dreConfig);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::configEngineRunState(
+ PositioningEngineMask engType, LocEngineRunState engState) {
+ uint32_t id = 0;
+ pthread_mutex_lock(&gDataMutex);
+
+ if (gData.gnssInterface != NULL) {
+ id = gData.gnssInterface->configEngineRunState(engType, engState);
+ } else {
+ LOC_LOGe("No gnss interface available for Location Control API");
+ }
+
+ pthread_mutex_unlock(&gDataMutex);
+ return id;
+}
+
+uint32_t LocationControlAPI::setOptInStatus(bool userConsent) {
+ void* libHandle = nullptr;
+ uint32_t sessionId = 0;
+ setOptInStatusGetter* setter = (setOptInStatusGetter*)dlGetSymFromLib(libHandle,
+ "liblocationservice_glue.so", "setOptInStatus");
+ if (setter != nullptr) {
+ sessionId = (*setter)(userConsent, &gData.controlCallbacks.responseCb);
+ } else {
+ LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
+ }
+ return sessionId;
+}
diff --git a/gps/location/LocationAPI.h b/gps/location/LocationAPI.h
new file mode 100644
index 0000000..7c70506
--- /dev/null
+++ b/gps/location/LocationAPI.h
@@ -0,0 +1,512 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LOCATIONAPI_H
+#define LOCATIONAPI_H
+
+#include "ILocationAPI.h"
+
+class LocationAPI : public ILocationAPI
+{
+private:
+ LocationAPI();
+ ~LocationAPI();
+
+public:
+ /* creates an instance to LocationAPI object.
+ Will return NULL if mandatory parameters are invalid or if the maximum number
+ of instances have been reached */
+ static LocationAPI* createInstance(LocationCallbacks&);
+
+ /* destroy/cleans up the instance, which should be called when LocationControlAPI object is
+ no longer needed. LocationControlAPI* returned from createInstance will no longer valid
+ after destroy is called.
+ If the caller allocates the memory for LocationControlCallbacks used in
+ LocationControlAPI::createInstance, then the caller must ensure that the memory still remains
+ valid until destroyCompleteCb is invoked.
+ */
+ void destroy(locationApiDestroyCompleteCallback destroyCompleteCb=nullptr);
+
+ void onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType);
+
+ /* updates/changes the callbacks that will be called.
+ mandatory callbacks must be present for callbacks to be successfully updated
+ no return value */
+ virtual void updateCallbacks(LocationCallbacks&) override;
+
+ /* ================================== TRACKING ================================== */
+
+ /* startTracking starts a tracking session, which returns a session id that will be
+ used by the other tracking APIs and also in the responseCallback to match command
+ with response. locations are reported on the trackingCallback passed in createInstance
+ periodically according to LocationOptions.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successfully started
+ LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress
+ LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed in createInstance
+ LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameter is invalid */
+ virtual uint32_t startTracking(TrackingOptions&) override;
+
+ /* stopTracking stops a tracking session associated with id parameter.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
+ virtual void stopTracking(uint32_t id) override;
+
+ /* updateTrackingOptions changes the TrackingOptions of a tracking session associated with id
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameters are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
+ virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) override;
+
+ /* ================================== BATCHING ================================== */
+
+ /* startBatching starts a batching session, which returns a session id that will be
+ used by the other batching APIs and also in the responseCallback to match command
+ with response. locations are reported on the batchingCallback passed in createInstance
+ periodically according to LocationOptions. A batching session starts tracking on
+ the low power processor and delivers them in batches by the batchingCallback when
+ the batch is full or when getBatchedLocations is called. This allows for the processor
+ that calls this API to sleep when the low power processor can batch locations in the
+ backgroup and wake up the processor calling the API only when the batch is full, thus
+ saving power
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress
+ LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance
+ LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid
+ LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */
+ virtual uint32_t startBatching(BatchingOptions&) override;
+
+ /* stopBatching stops a batching session associated with id parameter.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */
+ virtual void stopBatching(uint32_t id) override;
+
+ /* updateBatchingOptions changes the BatchingOptions of a batching session associated with id
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if BatchingOptions parameters are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
+ virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) override;
+
+ /* getBatchedLocations gets a number of locations that are currently stored/batched
+ on the low power processor, delivered by the batchingCallback passed in createInstance.
+ Location are then deleted from the batch stored on the low power processor.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call
+ LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
+ virtual void getBatchedLocations(uint32_t id, size_t count) override;
+
+ /* ================================== GEOFENCE ================================== */
+
+ /* addGeofences adds any number of geofences and returns an array of geofence ids that
+ will be used by the other geofence APIs and also in the collectiveResponseCallback to
+ match command with response. The geofenceBreachCallback will deliver the status of each
+ geofence according to the GeofenceOption for each. The geofence id array returned will
+ be valid until the collectiveResponseCallback is called and has returned.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */
+ virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) override;
+
+ /* removeGeofences removes any number of geofences. Caller should delete ids array after
+ removeGeofences returneds.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void removeGeofences(size_t count, uint32_t* ids) override;
+
+ /* modifyGeofences modifies any number of geofences. Caller should delete ids array after
+ modifyGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */
+ virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) override;
+
+ /* pauseGeofences pauses any number of geofences, which is similar to removeGeofences,
+ only that they can be resumed at any time. Caller should delete ids array after
+ pauseGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void pauseGeofences(size_t count, uint32_t* ids) override;
+
+ /* resumeGeofences resumes any number of geofences that are currently paused. Caller should
+ delete ids array after resumeGeofences returns.
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
+ virtual void resumeGeofences(size_t count, uint32_t* ids) override;
+
+ /* ================================== GNSS ====================================== */
+
+ /* gnssNiResponse is called in response to a gnssNiCallback.
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid
+ LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */
+ virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override;
+
+ /* ================================== NETWORK PROVIDER =========================== */
+
+ /* enableNetworkProvider enables Network Provider */
+ virtual void enableNetworkProvider();
+
+ /* disableNetworkProvider disables Network Provider */
+ virtual void disableNetworkProvider();
+
+ /* startNetworkLocation start a single shot network location request */
+ virtual void startNetworkLocation(trackingCallback* callback);
+
+ /* stopNetworkLocation stop any ongoing network location request */
+ virtual void stopNetworkLocation(trackingCallback* callback);
+};
+
+typedef struct {
+ size_t size; // set to sizeof(LocationControlCallbacks)
+ responseCallback responseCb; // mandatory
+ collectiveResponseCallback collectiveResponseCb; // mandatory
+ gnssConfigCallback gnssConfigCb; // optional
+} LocationControlCallbacks;
+
+class LocationControlAPI : public ILocationControlAPI
+{
+private:
+ LocationControlAPI();
+ ~LocationControlAPI();
+
+public:
+ /* creates an instance to LocationControlAPI object.
+ Will return NULL if mandatory parameters are invalid or if the maximum number
+ of instances have been reached. Only once instance allowed */
+ static LocationControlAPI* createInstance(LocationControlCallbacks&);
+
+ /* destroy/cleans up the instance, which should be called when LocationControlAPI object is
+ no longer needed. LocationControlAPI* returned from createInstance will no longer valid
+ after destroy is called */
+ void destroy();
+
+ /* enable will enable specific location technology to be used for calculation locations and
+ will effectively start a control session if call is successful, which returns a session id
+ that will be returned in responseCallback to match command with response. The session id is
+ also needed to call the disable command.
+ This effect is global for all clients of LocationAPI
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ALREADY_STARTED if an enable was already called for this techType
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
+ uint32_t enable(LocationTechnologyType techType);
+
+ /* disable will disable specific location technology to be used for calculation locations and
+ effectively ends the control session if call is successful.
+ id parameter is the session id that was returned in enable responseCallback for techType.
+ The session id is no longer valid after disable's responseCallback returns success.
+ This effect is global for all clients of LocationAPI
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_ID_UNKNOWN if id was not returned from responseCallback from enable
+ LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
+ void disable(uint32_t id);
+
+ /* gnssUpdateConfig updates the gnss specific configuration, which returns a session id array
+ with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits.
+ The response for each config that is set will be returned in collectiveResponseCallback.
+ The session id array returned will be valid until the collectiveResponseCallback is called
+ and has returned. This effect is global for all clients of LocationAPI
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
+ LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason
+
+ PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
+ The memory must be freed by delete [].*/
+ virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) override;
+
+ /* gnssGetConfig fetches the current constellation and SV configuration
+ on the GNSS engine.
+ Returns a session id array with an id for each of the bits set in
+ the mask parameter, order from low bits to high bits.
+ Response is sent via the registered gnssConfigCallback.
+ This effect is global for all clients of LocationAPI
+ collectiveResponseCallback returns:
+ LOCATION_ERROR_SUCCESS if session was successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameter is invalid
+ LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback
+ was passed in createInstance
+ LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration
+ is not supported
+
+ PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
+ The memory must be freed by delete [].*/
+ uint32_t* gnssGetConfig(GnssConfigFlagsMask mask);
+
+ /* delete specific gnss aiding data for testing, which returns a session id
+ that will be returned in responseCallback to match command with response.
+ Only allowed in userdebug builds. This effect is global for all clients of LocationAPI
+ responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */
+ virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override;
+
+ /** @brief
+ Configure the constellation and SVs to be used by the GNSS engine on
+ modem.
+
+ @param
+ constellationEnablementConfig: configuration to enable/disable SV
+ constellation to be used by SPE engine. When size in
+ constellationEnablementConfig is set to 0, this indicates to reset SV
+ constellation configuration to modem NV default.
+
+ blacklistSvConfig: configuration to blacklist or unblacklist SVs
+ used by SPE engine
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configConstellations(
+ const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig) override;
+
+ /** @brief
+ Configure the secondary band of constellations to be used by
+ the GNSS engine on modem.
+
+ @param
+ secondaryBandConfig: configuration the secondary band usage
+ for SPE engine
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configConstellationSecondaryBand(
+ const GnssSvTypeConfig& secondaryBandConfig) override;
+
+ /** @brief
+ Enable or disable the constrained time uncertainty feature.
+
+ @param
+ enable: true to enable the constrained time uncertainty
+ feature and false to disable the constrainted time
+ uncertainty feature.
+
+ @param
+ tuncThreshold: this specifies the time uncertainty threshold
+ that gps engine need to maintain, in units of milli-seconds.
+ Default is 0.0 meaning that modem default value of time
+ uncertainty threshold will be used. This parameter is
+ ignored when requesting to disable this feature.
+
+ @param
+ energyBudget: this specifies the power budget that gps
+ engine is allowed to spend to maintain the time uncertainty.
+ Default is 0 meaning that GPS engine is not constained by
+ power budget and can spend as much power as needed. The
+ parameter need to be specified in units of 0.1 milli watt
+ second. This parameter is ignored requesting to disable this
+ feature.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters
+ are invalid
+ */
+ virtual uint32_t configConstrainedTimeUncertainty(
+ bool enable, float tuncThreshold = 0.0,
+ uint32_t energyBudget = 0) override;
+
+ /** @brief
+ Enable or disable position assisted clock estimator feature.
+
+ @param
+ enable: true to enable position assisted clock estimator and
+ false to disable the position assisted clock estimator
+ feature.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configPositionAssistedClockEstimator(bool enable) override;
+
+ /** @brief
+ Sets the lever arm parameters for the vehicle.
+
+ @param
+ configInfo: lever arm configuration info regarding below two
+ types of lever arm info:
+ a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial
+ measurement unit.
+ b: lever arm parameters regarding the OPF (output frame)
+ w.r.t the origin (at the GPS Antenna). Vehicle manufacturers
+ prefer the position output to be tied to a specific point in
+ the vehicle rather than where the antenna is placed
+ (midpoint of the rear axle is typical).
+
+ Caller can choose types of lever arm info to configure via the
+ leverMarkTypeMask.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) override;
+
+ /** @brief
+ Configure the robust location setting.
+
+ @param
+ enable: true to enable robust location and false to disable
+ robust location.
+
+ @param
+ enableForE911: true to enable robust location when device is
+ on E911 session and false to disable on E911 session.
+ This parameter is only valid if robust location is enabled.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configRobustLocation(bool enable, bool enableForE911) override;
+
+ /** @brief
+ Config the minimal GPS week used by modem GNSS engine.
+
+ @param
+ minGpsWeek: minimal GPS week to be used by modem GNSS engine.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) override;
+
+ /** @brief
+ Configure the vehicle body-to-Sensor mount parameters and
+ other parameters for dead reckoning position engine.
+
+ @param
+ dreConfig: vehicle body-to-Sensor mount angles and other
+ parameters.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configDeadReckoningEngineParams(
+ const DeadReckoningEngineConfig& dreConfig) override;
+
+ /** @brief
+ This API is used to instruct the specified engine to be in
+ the pause/resume state. <br/>
+
+ When the engine is placed in paused state, the engine will
+ stop. If there is an on-going session, engine will no longer
+ produce fixes. In the paused state, calling API to delete
+ aiding data from the paused engine may not have effect.
+ Request to delete Aiding data shall be issued after
+ engine resume. <br/>
+
+ Currently, only DRE engine will support pause/resume
+ request. responseCb() will return not supported when request
+ is made to pause/resume none-DRE engine. <br/>
+
+ Request to pause/resume DRE engine can be made with or
+ without an on-going session. With QDR engine, on resume, GNSS
+ position & heading re-acquisition is needed for DR engine to
+ engage. If DR engine is already in the requested state, the
+ request will be no-op. <br/>
+
+ @param
+ engType: the engine that is instructed to change its run
+ state. <br/>
+
+ engState: the new engine run state that the engine is
+ instructed to be in. <br/>
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response. This effect is global for all
+ clients of LocationAPI responseCallback returns:
+ LOCATION_ERROR_SUCCESS if successful
+ LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
+ */
+ virtual uint32_t configEngineRunState(PositioningEngineMask engType,
+ LocEngineRunState engState) override;
+
+ /** @brief
+ Set the EULA opt-in status from system user. This is used as consent to
+ use network-based positioning.
+
+ @param
+ userConsnt: user agrees to use GTP service or not.
+
+ @return
+ A session id that will be returned in responseCallback to
+ match command with response.
+ */
+ virtual uint32_t setOptInStatus(bool userConsent);
+};
+
+#endif /* LOCATIONAPI_H */
diff --git a/gps/location/LocationAPIClientBase.cpp b/gps/location/LocationAPIClientBase.cpp
new file mode 100644
index 0000000..4865a16
--- /dev/null
+++ b/gps/location/LocationAPIClientBase.cpp
@@ -0,0 +1,977 @@
+/* Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_APIClientBase"
+
+#include <loc_pla.h>
+#include <log_util.h>
+#include <inttypes.h>
+#include <loc_cfg.h>
+#include "LocationAPIClientBase.h"
+
+#define GEOFENCE_SESSION_ID 0xFFFFFFFF
+#define CONFIG_SESSION_ID 0xFFFFFFFF
+
+// LocationAPIControlClient
+LocationAPIControlClient::LocationAPIControlClient() :
+ mEnabled(false)
+{
+ pthread_mutex_init(&mMutex, nullptr);
+
+ for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
+ mRequestQueues[i].reset((uint32_t)0);
+ }
+
+ memset(&mConfig, 0, sizeof(GnssConfig));
+
+ LocationControlCallbacks locationControlCallbacks;
+ locationControlCallbacks.size = sizeof(LocationControlCallbacks);
+
+ locationControlCallbacks.responseCb =
+ [this](LocationError error, uint32_t id) {
+ onCtrlResponseCb(error, id);
+ };
+ locationControlCallbacks.collectiveResponseCb =
+ [this](size_t count, LocationError* errors, uint32_t* ids) {
+ onCtrlCollectiveResponseCb(count, errors, ids);
+ };
+
+ mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks);
+}
+
+LocationAPIControlClient::~LocationAPIControlClient()
+{
+ pthread_mutex_lock(&mMutex);
+
+ if (mLocationControlAPI) {
+ mLocationControlAPI->destroy();
+ mLocationControlAPI = nullptr;
+ }
+
+ for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
+ mRequestQueues[i].reset((uint32_t)0);
+ }
+
+ pthread_mutex_unlock(&mMutex);
+
+ pthread_mutex_destroy(&mMutex);
+}
+
+uint32_t LocationAPIControlClient::locAPIGnssDeleteAidingData(GnssAidingData& data)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationControlAPI) {
+ uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].reset(session);
+ mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].push(new GnssDeleteAidingDataRequest(*this));
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+uint32_t LocationAPIControlClient::locAPIEnable(LocationTechnologyType techType)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mEnabled) {
+ // just return success if already enabled
+ retVal = LOCATION_ERROR_SUCCESS;
+ } else if (mLocationControlAPI) {
+ uint32_t session = mLocationControlAPI->enable(techType);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ mRequestQueues[CTRL_REQUEST_CONTROL].reset(session);
+ mRequestQueues[CTRL_REQUEST_CONTROL].push(new EnableRequest(*this));
+ retVal = LOCATION_ERROR_SUCCESS;
+ mEnabled = true;
+ } else {
+ LOC_LOGE("%s:%d] failed.", __FUNCTION__, __LINE__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+void LocationAPIControlClient::locAPIDisable()
+{
+ pthread_mutex_lock(&mMutex);
+ if (mEnabled && mLocationControlAPI) {
+ uint32_t session = 0;
+ session = mRequestQueues[CTRL_REQUEST_CONTROL].getSession();
+ if (session > 0) {
+ mRequestQueues[CTRL_REQUEST_CONTROL].push(new DisableRequest(*this));
+ mLocationControlAPI->disable(session);
+ mEnabled = false;
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+
+ pthread_mutex_lock(&mMutex);
+ if (mLocationControlAPI) {
+ if (mConfig.equals(config)) {
+ LOC_LOGv("GnssConfig is identical to previous call");
+ retVal = LOCATION_ERROR_SUCCESS;
+ } else {
+ mConfig = config;
+ uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
+ LOC_LOGv("gnssUpdateConfig return array: %p", idArray);
+ if (nullptr != idArray) {
+ if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr()) {
+ mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].reset(idArray);
+ }
+ mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this));
+ retVal = LOCATION_ERROR_SUCCESS;
+ delete [] idArray;
+ }
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ return retVal;
+}
+
+uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+
+ pthread_mutex_lock(&mMutex);
+ if (mLocationControlAPI) {
+
+ uint32_t* idArray = mLocationControlAPI->gnssGetConfig(mask);
+ LOC_LOGv("gnssGetConfig return array: %p", idArray);
+ if (nullptr != idArray) {
+ if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr()) {
+ mRequestQueues[CTRL_REQUEST_CONFIG_GET].reset(idArray);
+ }
+ mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this));
+ retVal = LOCATION_ERROR_SUCCESS;
+ delete [] idArray;
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ return retVal;
+}
+
+void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id)
+{
+ if (error != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
+ } else {
+ LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
+ }
+ LocationAPIRequest* request = getRequestBySession(id);
+ if (request) {
+ request->onResponse(error, id);
+ delete request;
+ }
+}
+
+void LocationAPIControlClient::onCtrlCollectiveResponseCb(
+ size_t count, LocationError* errors, uint32_t* ids)
+{
+ for (size_t i = 0; i < count; i++) {
+ if (errors[i] != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ } else {
+ LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ }
+ }
+ LocationAPIRequest* request = getRequestBySessionArrayPtr(ids);
+ if (request) {
+ request->onCollectiveResponse(count, errors, ids);
+ delete request;
+ }
+}
+
+LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session)
+{
+ pthread_mutex_lock(&mMutex);
+ LocationAPIRequest* request = nullptr;
+
+ if (mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].getSession() == session) {
+ request = mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].pop();
+ } else if (mRequestQueues[CTRL_REQUEST_CONTROL].getSession() == session) {
+ request = mRequestQueues[CTRL_REQUEST_CONTROL].pop();
+ }
+
+ pthread_mutex_unlock(&mMutex);
+ return request;
+}
+
+LocationAPIRequest*
+LocationAPIControlClient::getRequestBySessionArrayPtr(
+ uint32_t* sessionArrayPtr)
+{
+ pthread_mutex_lock(&mMutex);
+ LocationAPIRequest* request = nullptr;
+
+ if (mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr() == sessionArrayPtr) {
+ request = mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].pop();
+ } else if (mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr() == sessionArrayPtr) {
+ request = mRequestQueues[CTRL_REQUEST_CONFIG_GET].pop();
+ }
+
+ pthread_mutex_unlock(&mMutex);
+ return request;
+}
+
+// LocationAPIClientBase
+LocationAPIClientBase::LocationAPIClientBase() :
+ mGeofenceBreachCallback(nullptr),
+ mBatchingStatusCallback(nullptr),
+ mLocationAPI(nullptr),
+ mBatchSize(-1),
+ mTracking(false)
+{
+
+ // use recursive mutex, in case callback come from the same thread
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mMutex, &attr);
+
+ for (int i = 0; i < REQUEST_MAX; i++) {
+ mRequestQueues[i].reset((uint32_t)0);
+ }
+}
+
+void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks)
+{
+ pthread_mutex_lock(&mMutex);
+
+ if (locationCallbacks.geofenceBreachCb != nullptr) {
+ mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb;
+ locationCallbacks.geofenceBreachCb =
+ [this](GeofenceBreachNotification geofenceBreachNotification) {
+ beforeGeofenceBreachCb(geofenceBreachNotification);
+ };
+ }
+
+ locationCallbacks.capabilitiesCb =
+ [this](LocationCapabilitiesMask capabilitiesMask) {
+ onCapabilitiesCb(capabilitiesMask);
+ };
+ locationCallbacks.responseCb = [this](LocationError error, uint32_t id) {
+ onResponseCb(error, id);
+ };
+ locationCallbacks.collectiveResponseCb =
+ [this](size_t count, LocationError* errors, uint32_t* ids) {
+ onCollectiveResponseCb(count, errors, ids);
+ };
+
+ if (locationCallbacks.batchingStatusCb != nullptr) {
+ mBatchingStatusCallback = locationCallbacks.batchingStatusCb;
+ locationCallbacks.batchingStatusCb =
+ [this](BatchingStatusInfo batchStatus, std::list<uint32_t> & tripCompletedList) {
+ beforeBatchingStatusCb(batchStatus, tripCompletedList);
+ };
+ }
+
+ if (mLocationAPI == nullptr ) {
+ mLocationAPI = LocationAPI::createInstance(locationCallbacks);
+ } else {
+ mLocationAPI->updateCallbacks(locationCallbacks);
+ }
+
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::destroy()
+{
+ LOC_LOGD("LocationAPIClientBase::destroy()");
+
+ pthread_mutex_lock(&mMutex);
+
+ mGeofenceBreachCallback = nullptr;
+
+ for (int i = 0; i < REQUEST_MAX; i++) {
+ mRequestQueues[i].reset((uint32_t)0);
+ }
+
+ LocationAPI* localHandle = nullptr;
+ if (nullptr != mLocationAPI) {
+ localHandle = mLocationAPI;
+ mLocationAPI = nullptr;
+ }
+
+ pthread_mutex_unlock(&mMutex);
+
+ // Invoking destroy has the possibility of destroy complete callback
+ // being invoked right away in the same context, hence no instance
+ // member must be accessed after the destroy call.
+ if (nullptr != localHandle) {
+ localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();});
+ }
+}
+
+LocationAPIClientBase::~LocationAPIClientBase()
+{
+ pthread_mutex_destroy(&mMutex);
+}
+
+void LocationAPIClientBase::onLocationApiDestroyCompleteCb()
+{
+ LOC_LOGD("LocationAPIClientBase::onLocationApiDestroyCompleteCb()");
+ delete this;
+}
+
+uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ if (mTracking) {
+ LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__);
+ } else {
+ uint32_t session = mLocationAPI->startTracking(options);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ // onResponseCb might be called from other thread immediately after
+ // startTracking returns, so we are not going to unlock mutex
+ // until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING]
+ mRequestQueues[REQUEST_TRACKING].reset(session);
+ mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
+ mTracking = true;
+ }
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+void LocationAPIClientBase::locAPIStopTracking()
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t session = 0;
+ session = mRequestQueues[REQUEST_TRACKING].getSession();
+ if (session > 0) {
+ mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
+ mLocationAPI->stopTracking(session);
+ mTracking = false;
+ } else {
+ LOC_LOGD("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t session = 0;
+ session = mRequestQueues[REQUEST_TRACKING].getSession();
+ if (session > 0) {
+ mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
+ mLocationAPI->updateTrackingOptions(session, options);
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+int32_t LocationAPIClientBase::locAPIGetBatchSize()
+{
+ if (mBatchSize == -1) {
+ const loc_param_s_type flp_conf_param_table[] =
+ {
+ {"BATCH_SIZE", &mBatchSize, nullptr, 'n'},
+ };
+ UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
+ if (mBatchSize < 0) {
+ // set mBatchSize to 0 if we got an illegal value from config file
+ mBatchSize = 0;
+ }
+ }
+ return mBatchSize;
+}
+
+uint32_t LocationAPIClientBase::locAPIStartSession(
+ uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+
+ if (mSessionBiDict.hasId(id)) {
+ LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id);
+ retVal = LOCATION_ERROR_ALREADY_STARTED;
+ } else {
+ uint32_t trackingSession = 0;
+ uint32_t batchingSession = 0;
+
+ if (sessionMode == SESSION_MODE_ON_FIX) {
+ trackingSession = mLocationAPI->startTracking(options);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
+ mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
+ } else {
+ // Fill in the batch mode
+ BatchingOptions batchOptions = {};
+ batchOptions.size = sizeof(BatchingOptions);
+ switch (sessionMode) {
+ case SESSION_MODE_ON_FULL:
+ batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
+ break;
+ case SESSION_MODE_ON_TRIP_COMPLETED:
+ batchOptions.batchingMode = BATCHING_MODE_TRIP;
+ break;
+ default:
+ batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
+ break;
+ }
+
+ // Populate location option values
+ batchOptions.minDistance = options.minDistance;
+ batchOptions.minInterval = options.minInterval;
+ batchOptions.mode = options.mode;
+
+ batchingSession = mLocationAPI->startBatching(batchOptions);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
+ mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
+ mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
+ }
+
+ uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
+ batchingSession : trackingSession);
+
+ SessionEntity entity;
+ entity.id = id;
+ entity.trackingSession = trackingSession;
+ entity.batchingSession = batchingSession;
+ entity.sessionMode = sessionMode;
+ mSessionBiDict.set(id, session, entity);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+
+ if (mSessionBiDict.hasId(id)) {
+ SessionEntity entity = mSessionBiDict.getExtById(id);
+
+ uint32_t trackingSession = entity.trackingSession;
+ uint32_t batchingSession = entity.batchingSession;
+ uint32_t sMode = entity.sessionMode;
+
+ if (sMode == SESSION_MODE_ON_FIX) {
+ mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this));
+ mLocationAPI->stopTracking(trackingSession);
+ } else {
+ mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this));
+ mLocationAPI->stopBatching(batchingSession);
+ }
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ } else {
+ retVal = LOCATION_ERROR_ID_UNKNOWN;
+ LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
+ }
+
+ }
+ pthread_mutex_unlock(&mMutex);
+ return retVal;
+}
+
+uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(
+ uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+
+ if (mSessionBiDict.hasId(id)) {
+ SessionEntity entity = mSessionBiDict.getExtById(id);
+
+ uint32_t trackingSession = entity.trackingSession;
+ uint32_t batchingSession = entity.batchingSession;
+ uint32_t sMode = entity.sessionMode;
+
+ if (sessionMode == SESSION_MODE_ON_FIX) {
+ // we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION],
+ // even if this update request will stop batching and then start tracking.
+ mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this));
+ if (sMode == SESSION_MODE_ON_FIX) {
+ mLocationAPI->updateTrackingOptions(trackingSession, options);
+ } else {
+ // stop batching
+ // batchingSession will be removed from mSessionBiDict soon,
+ // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
+ mLocationAPI->stopBatching(batchingSession);
+ batchingSession = 0;
+ mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
+
+ // start tracking
+ trackingSession = mLocationAPI->startTracking(options);
+ LOC_LOGI("%s:%d] start new session: %d",
+ __FUNCTION__, __LINE__, trackingSession);
+ }
+ } else {
+ // we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION],
+ // even if this update request will stop tracking and then start batching.
+ mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this));
+ BatchingOptions batchOptions = {};
+ batchOptions.size = sizeof(BatchingOptions);
+ switch (sessionMode) {
+ case SESSION_MODE_ON_FULL:
+ batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
+ break;
+ case SESSION_MODE_ON_TRIP_COMPLETED:
+ batchOptions.batchingMode = BATCHING_MODE_TRIP;
+ break;
+ default:
+ batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
+ break;
+ }
+
+ if (sMode == SESSION_MODE_ON_FIX) {
+ // stop tracking
+ // trackingSession will be removed from mSessionBiDict soon,
+ // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
+ mLocationAPI->stopTracking(trackingSession);
+ trackingSession = 0;
+
+ // Populate location option values
+ batchOptions.minDistance = options.minDistance;
+ batchOptions.minInterval = options.minInterval;
+ batchOptions.mode = options.mode;
+
+ // start batching
+ batchingSession = mLocationAPI->startBatching(batchOptions);
+ LOC_LOGI("%s:%d] start new session: %d",
+ __FUNCTION__, __LINE__, batchingSession);
+ mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
+ } else {
+ mLocationAPI->updateBatchingOptions(batchingSession, batchOptions);
+ }
+
+ }
+
+ uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
+ batchingSession : trackingSession);
+
+ entity.trackingSession = trackingSession;
+ entity.batchingSession = batchingSession;
+ entity.sessionMode = sessionMode;
+ // remove the old values from mSessionBiDict before we add a new one.
+ mSessionBiDict.rmById(id);
+ mSessionBiDict.set(id, session, entity);
+
+ retVal = LOCATION_ERROR_SUCCESS;
+ } else {
+ retVal = LOCATION_ERROR_ID_UNKNOWN;
+ LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ return retVal;
+}
+
+uint32_t LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t count)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ if (mSessionBiDict.hasId(id)) {
+ SessionEntity entity = mSessionBiDict.getExtById(id);
+ if (entity.sessionMode != SESSION_MODE_ON_FIX) {
+ uint32_t batchingSession = entity.batchingSession;
+ mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
+ mLocationAPI->getBatchedLocations(batchingSession, count);
+ retVal = LOCATION_ERROR_SUCCESS;
+ } else {
+ LOC_LOGE("%s:%d] Unsupported for session id: %d, mode is SESSION_MODE_ON_FIX",
+ __FUNCTION__, __LINE__, id);
+ retVal = LOCATION_ERROR_NOT_SUPPORTED;
+ }
+ } else {
+ retVal = LOCATION_ERROR_ID_UNKNOWN;
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, id);
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+uint32_t LocationAPIClientBase::locAPIAddGeofences(
+ size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data)
+{
+ uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() != GEOFENCE_SESSION_ID) {
+ mRequestQueues[REQUEST_GEOFENCE].reset(GEOFENCE_SESSION_ID);
+ }
+ uint32_t* sessions = mLocationAPI->addGeofences(count, options, data);
+ if (sessions) {
+ LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions);
+ mRequestQueues[REQUEST_GEOFENCE].push(new AddGeofencesRequest(*this));
+
+ for (size_t i = 0; i < count; i++) {
+ mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
+ }
+ retVal = LOCATION_ERROR_SUCCESS;
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ return retVal;
+}
+
+void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ if (sessions == NULL) {
+ LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
+ __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
+ pthread_mutex_unlock(&mMutex);
+ return;
+ }
+
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
+ BiDict<GeofenceBreachTypeMask>* removedGeofenceBiDict =
+ new BiDict<GeofenceBreachTypeMask>();
+ size_t j = 0;
+ for (size_t i = 0; i < count; i++) {
+ sessions[j] = mGeofenceBiDict.getSession(ids[i]);
+ if (sessions[j] > 0) {
+ GeofenceBreachTypeMask type = mGeofenceBiDict.getExtBySession(sessions[j]);
+ mGeofenceBiDict.rmBySession(sessions[j]);
+ removedGeofenceBiDict->set(ids[i], sessions[j], type);
+ j++;
+ }
+ }
+ if (j > 0) {
+ mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this,
+ removedGeofenceBiDict));
+ mLocationAPI->removeGeofences(j, sessions);
+ } else {
+ delete(removedGeofenceBiDict);
+ }
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
+ mRequestQueues[REQUEST_GEOFENCE].getSession());
+ }
+
+ free(sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIModifyGeofences(
+ size_t count, uint32_t* ids, GeofenceOption* options)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ if (sessions == NULL) {
+ LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
+ __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
+ pthread_mutex_unlock(&mMutex);
+ return;
+ }
+
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
+ size_t j = 0;
+ for (size_t i = 0; i < count; i++) {
+ sessions[j] = mGeofenceBiDict.getSession(ids[i]);
+ if (sessions[j] > 0) {
+ mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask);
+ j++;
+ }
+ }
+ if (j > 0) {
+ mRequestQueues[REQUEST_GEOFENCE].push(new ModifyGeofencesRequest(*this));
+ mLocationAPI->modifyGeofences(j, sessions, options);
+ }
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
+ mRequestQueues[REQUEST_GEOFENCE].getSession());
+ }
+
+ free(sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ if (sessions == NULL) {
+ LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
+ __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
+ pthread_mutex_unlock(&mMutex);
+ return;
+ }
+
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
+ size_t j = 0;
+ for (size_t i = 0; i < count; i++) {
+ sessions[j] = mGeofenceBiDict.getSession(ids[i]);
+ if (sessions[j] > 0) {
+ j++;
+ }
+ }
+ if (j > 0) {
+ mRequestQueues[REQUEST_GEOFENCE].push(new PauseGeofencesRequest(*this));
+ mLocationAPI->pauseGeofences(j, sessions);
+ }
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
+ mRequestQueues[REQUEST_GEOFENCE].getSession());
+ }
+
+ free(sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIResumeGeofences(
+ size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ if (sessions == NULL) {
+ LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
+ __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
+ pthread_mutex_unlock(&mMutex);
+ return;
+ }
+
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
+ size_t j = 0;
+ for (size_t i = 0; i < count; i++) {
+ sessions[j] = mGeofenceBiDict.getSession(ids[i]);
+ if (sessions[j] > 0) {
+ if (mask) {
+ mGeofenceBiDict.set(ids[i], sessions[j], mask[i]);
+ }
+ j++;
+ }
+ }
+ if (j > 0) {
+ mRequestQueues[REQUEST_GEOFENCE].push(new ResumeGeofencesRequest(*this));
+ mLocationAPI->resumeGeofences(j, sessions);
+ }
+ } else {
+ LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
+ mRequestQueues[REQUEST_GEOFENCE].getSession());
+ }
+
+ free(sessions);
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::locAPIRemoveAllGeofences()
+{
+ std::vector<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions();
+ if (sessionsVec.size() > 0) {
+ locAPIRemoveGeofences(sessionsVec.size(), &sessionsVec[0]);
+ }
+}
+
+void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
+{
+ pthread_mutex_lock(&mMutex);
+ if (mLocationAPI) {
+ uint32_t session = id;
+ mLocationAPI->gnssNiResponse(id, response);
+ LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
+ mRequestQueues[REQUEST_NIRESPONSE].reset(session);
+ mRequestQueues[REQUEST_NIRESPONSE].push(new GnssNiResponseRequest(*this));
+ }
+ pthread_mutex_unlock(&mMutex);
+}
+
+void LocationAPIClientBase::beforeGeofenceBreachCb(
+ GeofenceBreachNotification geofenceBreachNotification)
+{
+ uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count);
+ uint32_t* backup = geofenceBreachNotification.ids;
+ size_t n = geofenceBreachNotification.count;
+ geofenceBreachCallback genfenceCallback = nullptr;
+
+ if (ids == NULL) {
+ LOC_LOGE("%s:%d] Failed to alloc %zu bytes",
+ __FUNCTION__, __LINE__,
+ sizeof(uint32_t) * geofenceBreachNotification.count);
+ return;
+ }
+
+ pthread_mutex_lock(&mMutex);
+ if (mGeofenceBreachCallback != nullptr) {
+ size_t count = 0;
+ for (size_t i = 0; i < n; i++) {
+ uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
+ GeofenceBreachTypeMask type =
+ mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]);
+ // if type == 0, we will not head into the fllowing block anyway.
+ // so we don't need to check id and type
+ if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER &&
+ (type & GEOFENCE_BREACH_ENTER_BIT)) ||
+ (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT &&
+ (type & GEOFENCE_BREACH_EXIT_BIT))
+ ) {
+ ids[count] = id;
+ count++;
+ }
+ }
+ geofenceBreachNotification.count = count;
+ geofenceBreachNotification.ids = ids;
+
+ genfenceCallback = mGeofenceBreachCallback;
+ }
+ pthread_mutex_unlock(&mMutex);
+
+ if (genfenceCallback != nullptr) {
+ genfenceCallback(geofenceBreachNotification);
+ }
+
+ // restore ids
+ geofenceBreachNotification.ids = backup;
+ geofenceBreachNotification.count = n;
+ free(ids);
+}
+
+void LocationAPIClientBase::beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
+ std::list<uint32_t> & tripCompletedList) {
+
+ // map the trip ids to the client ids
+ std::list<uint32_t> tripCompletedClientIdList;
+ tripCompletedClientIdList.clear();
+
+ if (batchStatus.batchingStatus == BATCHING_STATUS_TRIP_COMPLETED) {
+ for (auto itt = tripCompletedList.begin(); itt != tripCompletedList.end(); itt++) {
+ if (mSessionBiDict.hasSession(*itt)) {
+ SessionEntity sessEntity = mSessionBiDict.getExtBySession(*itt);
+
+ if (sessEntity.sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
+ tripCompletedClientIdList.push_back(sessEntity.id);
+ mSessionBiDict.rmBySession(*itt);
+ }
+ }
+ }
+ }
+
+ mBatchingStatusCallback(batchStatus, tripCompletedClientIdList);
+}
+
+void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id)
+{
+ if (error != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
+ } else {
+ LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
+ }
+ LocationAPIRequest* request = getRequestBySession(id);
+ if (request) {
+ request->onResponse(error, id);
+ delete request;
+ }
+}
+
+void LocationAPIClientBase::onCollectiveResponseCb(
+ size_t count, LocationError* errors, uint32_t* ids)
+{
+ for (size_t i = 0; i < count; i++) {
+ if (errors[i] != LOCATION_ERROR_SUCCESS) {
+ LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ } else {
+ LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
+ }
+ }
+ LocationAPIRequest* request = nullptr;
+ pthread_mutex_lock(&mMutex);
+ if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
+ request = mRequestQueues[REQUEST_GEOFENCE].pop();
+ }
+ pthread_mutex_unlock(&mMutex);
+ if (request) {
+ request->onCollectiveResponse(count, errors, ids);
+ delete request;
+ }
+}
+
+void LocationAPIClientBase::removeSession(uint32_t session) {
+ if (mSessionBiDict.hasSession(session)) {
+ mSessionBiDict.rmBySession(session);
+ }
+}
+
+LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session)
+{
+ pthread_mutex_lock(&mMutex);
+ LocationAPIRequest* request = nullptr;
+ for (int i = 0; i < REQUEST_MAX; i++) {
+ if (i != REQUEST_GEOFENCE &&
+ i != REQUEST_SESSION &&
+ mRequestQueues[i].getSession() == session) {
+ request = mRequestQueues[i].pop();
+ break;
+ }
+ }
+ if (request == nullptr) {
+ // Can't find a request with correct session,
+ // try to find it from mSessionBiDict
+ if (mSessionBiDict.hasSession(session)) {
+ request = mRequestQueues[REQUEST_SESSION].pop();
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ return request;
+}
diff --git a/gps/location/LocationAPIClientBase.h b/gps/location/LocationAPIClientBase.h
new file mode 100644
index 0000000..ac1ebe6
--- /dev/null
+++ b/gps/location/LocationAPIClientBase.h
@@ -0,0 +1,592 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LOCATION_API_CLINET_BASE_H
+#define LOCATION_API_CLINET_BASE_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <queue>
+#include <map>
+
+#include "LocationAPI.h"
+#include <loc_pla.h>
+#include <log_util.h>
+
+enum SESSION_MODE {
+ SESSION_MODE_NONE = 0,
+ SESSION_MODE_ON_FULL,
+ SESSION_MODE_ON_FIX,
+ SESSION_MODE_ON_TRIP_COMPLETED
+};
+
+enum REQUEST_TYPE {
+ REQUEST_TRACKING = 0,
+ REQUEST_SESSION,
+ REQUEST_GEOFENCE,
+ REQUEST_NIRESPONSE,
+ REQUEST_MAX,
+};
+
+enum CTRL_REQUEST_TYPE {
+ CTRL_REQUEST_DELETEAIDINGDATA = 0,
+ CTRL_REQUEST_CONTROL,
+ CTRL_REQUEST_CONFIG_UPDATE,
+ CTRL_REQUEST_CONFIG_GET,
+ CTRL_REQUEST_MAX,
+};
+
+class LocationAPIClientBase;
+
+class LocationAPIRequest {
+public:
+ LocationAPIRequest() {}
+ virtual ~LocationAPIRequest() {}
+ virtual void onResponse(LocationError /*error*/, uint32_t /*id*/) {}
+ virtual void onCollectiveResponse(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+};
+
+class RequestQueue {
+public:
+ RequestQueue(): mSession(0), mSessionArrayPtr(nullptr) {
+ }
+ virtual ~RequestQueue() {
+ reset((uint32_t)0);
+ }
+ void inline setSession(uint32_t session) { mSession = session; }
+ void inline setSessionArrayPtr(uint32_t* ptr) { mSessionArrayPtr = ptr; }
+ void reset(uint32_t session) {
+ LocationAPIRequest* request = nullptr;
+ while (!mQueue.empty()) {
+ request = mQueue.front();
+ mQueue.pop();
+ delete request;
+ }
+ mSession = session;
+ }
+ void reset(uint32_t* sessionArrayPtr) {
+ reset((uint32_t)0);
+ mSessionArrayPtr = sessionArrayPtr;
+ }
+ void push(LocationAPIRequest* request) {
+ mQueue.push(request);
+ }
+ LocationAPIRequest* pop() {
+ LocationAPIRequest* request = nullptr;
+ if (!mQueue.empty()) {
+ request = mQueue.front();
+ mQueue.pop();
+ }
+ return request;
+ }
+ uint32_t getSession() { return mSession; }
+ uint32_t* getSessionArrayPtr() { return mSessionArrayPtr; }
+private:
+ uint32_t mSession;
+ uint32_t* mSessionArrayPtr;
+ std::queue<LocationAPIRequest*> mQueue;
+};
+
+class LocationAPIControlClient {
+public:
+ LocationAPIControlClient();
+ virtual ~LocationAPIControlClient();
+ LocationAPIControlClient(const LocationAPIControlClient&) = delete;
+ LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete;
+
+ LocationAPIRequest* getRequestBySession(uint32_t session);
+ LocationAPIRequest* getRequestBySessionArrayPtr(uint32_t* sessionArrayPtr);
+
+ // LocationControlAPI
+ uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data);
+ uint32_t locAPIEnable(LocationTechnologyType techType);
+ void locAPIDisable();
+ uint32_t locAPIGnssUpdateConfig(GnssConfig config);
+ uint32_t locAPIGnssGetConfig(GnssConfigFlagsMask config);
+ inline LocationControlAPI* getControlAPI() { return mLocationControlAPI; }
+
+ // callbacks
+ void onCtrlResponseCb(LocationError error, uint32_t id);
+ void onCtrlCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
+
+ inline virtual void onGnssDeleteAidingDataCb(LocationError /*error*/) {}
+ inline virtual void onEnableCb(LocationError /*error*/) {}
+ inline virtual void onDisableCb(LocationError /*error*/) {}
+ inline virtual void onGnssUpdateConfigCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onGnssGetConfigCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+
+ class GnssDeleteAidingDataRequest : public LocationAPIRequest {
+ public:
+ GnssDeleteAidingDataRequest(LocationAPIControlClient& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onGnssDeleteAidingDataCb(error);
+ }
+ LocationAPIControlClient& mAPI;
+ };
+
+ class EnableRequest : public LocationAPIRequest {
+ public:
+ EnableRequest(LocationAPIControlClient& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onEnableCb(error);
+ }
+ LocationAPIControlClient& mAPI;
+ };
+
+ class DisableRequest : public LocationAPIRequest {
+ public:
+ DisableRequest(LocationAPIControlClient& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onDisableCb(error);
+ }
+ LocationAPIControlClient& mAPI;
+ };
+
+ class GnssUpdateConfigRequest : public LocationAPIRequest {
+ public:
+ GnssUpdateConfigRequest(LocationAPIControlClient& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
+ mAPI.onGnssUpdateConfigCb(count, errors, ids);
+ }
+ LocationAPIControlClient& mAPI;
+ };
+
+ class GnssGetConfigRequest : public LocationAPIRequest {
+ public:
+ GnssGetConfigRequest(LocationAPIControlClient& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
+ mAPI.onGnssGetConfigCb(count, errors, ids);
+ }
+ LocationAPIControlClient& mAPI;
+ };
+
+private:
+ pthread_mutex_t mMutex;
+ LocationControlAPI* mLocationControlAPI;
+ RequestQueue mRequestQueues[CTRL_REQUEST_MAX];
+ bool mEnabled;
+ GnssConfig mConfig;
+};
+
+class LocationAPIClientBase {
+public:
+ LocationAPIClientBase();
+ LocationAPIClientBase(const LocationAPIClientBase&) = delete;
+ LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
+
+ void destroy();
+ void onLocationApiDestroyCompleteCb();
+
+ void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
+ void removeSession(uint32_t session);
+ LocationAPIRequest* getRequestBySession(uint32_t session);
+
+ // LocationAPI
+ uint32_t locAPIStartTracking(TrackingOptions& trackingOptions);
+ void locAPIStopTracking();
+ void locAPIUpdateTrackingOptions(TrackingOptions& trackingOptions);
+
+ int32_t locAPIGetBatchSize();
+ uint32_t locAPIStartSession(
+ uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
+ uint32_t locAPIStopSession(uint32_t id);
+ uint32_t locAPIUpdateSessionOptions(
+ uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
+ uint32_t locAPIGetBatchedLocations(uint32_t id, size_t count);
+
+ uint32_t locAPIAddGeofences(size_t count, uint32_t* ids,
+ GeofenceOption* options, GeofenceInfo* data);
+ void locAPIRemoveGeofences(size_t count, uint32_t* ids);
+ void locAPIModifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options);
+ void locAPIPauseGeofences(size_t count, uint32_t* ids);
+ void locAPIResumeGeofences(size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask);
+ void locAPIRemoveAllGeofences();
+
+ void locAPIGnssNiResponse(uint32_t id, GnssNiResponse response);
+
+ // callbacks
+ void onResponseCb(LocationError error, uint32_t id);
+ void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
+
+ void beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification);
+
+ inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {}
+ inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {}
+ inline virtual void onGnssDataCb(GnssDataNotification /*gnssDataNotification*/) {}
+ inline virtual void onGnssMeasurementsCb(
+ GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {}
+
+ inline virtual void onTrackingCb(Location /*location*/) {}
+ inline virtual void onGnssSvCb(GnssSvNotification /*gnssSvNotification*/) {}
+ inline virtual void onStartTrackingCb(LocationError /*error*/) {}
+ inline virtual void onStopTrackingCb(LocationError /*error*/) {}
+ inline virtual void onUpdateTrackingOptionsCb(LocationError /*error*/) {}
+
+ inline virtual void onGnssLocationInfoCb(
+ GnssLocationInfoNotification /*gnssLocationInfoNotification*/) {}
+
+ inline virtual void onBatchingCb(size_t /*count*/, Location* /*location*/,
+ BatchingOptions /*batchingOptions*/) {}
+ inline virtual void onBatchingStatusCb(BatchingStatusInfo /*batchingStatus*/,
+ std::list<uint32_t> &/*listOfCompletedTrips*/) {}
+ void beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
+ std::list<uint32_t> & tripCompletedList);
+ inline virtual void onStartBatchingCb(LocationError /*error*/) {}
+ inline virtual void onStopBatchingCb(LocationError /*error*/) {}
+ inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {}
+ inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {}
+
+ inline virtual void onGeofenceBreachCb(
+ GeofenceBreachNotification /*geofenceBreachNotification*/) {}
+ inline virtual void onGeofenceStatusCb(
+ GeofenceStatusNotification /*geofenceStatusNotification*/) {}
+ inline virtual void onAddGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onRemoveGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onModifyGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onPauseGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+ inline virtual void onResumeGeofencesCb(
+ size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
+
+ inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {}
+ inline virtual void onGnssNiResponseCb(LocationError /*error*/) {}
+
+ inline virtual void onLocationSystemInfoCb(LocationSystemInfo /*locationSystemInfo*/) {}
+
+protected:
+ virtual ~LocationAPIClientBase();
+
+private:
+ // private inner classes
+ typedef struct {
+ uint32_t id;
+ uint32_t trackingSession;
+ uint32_t batchingSession;
+ uint32_t sessionMode;
+ } SessionEntity;
+
+ template<typename T>
+ class BiDict {
+ public:
+ BiDict() {
+ pthread_mutex_init(&mBiDictMutex, nullptr);
+ }
+ virtual ~BiDict() {
+ pthread_mutex_destroy(&mBiDictMutex);
+ }
+ bool hasId(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ bool ret = (mForwardMap.find(id) != mForwardMap.end());
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ bool hasSession(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ bool ret = (mBackwardMap.find(session) != mBackwardMap.end());
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ void set(uint32_t id, uint32_t session, T& ext) {
+ pthread_mutex_lock(&mBiDictMutex);
+ mForwardMap[id] = session;
+ mBackwardMap[session] = id;
+ mExtMap[session] = ext;
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ void clear() {
+ pthread_mutex_lock(&mBiDictMutex);
+ mForwardMap.clear();
+ mBackwardMap.clear();
+ mExtMap.clear();
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ void rmById(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ mBackwardMap.erase(mForwardMap[id]);
+ mExtMap.erase(mForwardMap[id]);
+ mForwardMap.erase(id);
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ void rmBySession(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ mForwardMap.erase(mBackwardMap[session]);
+ mBackwardMap.erase(session);
+ mExtMap.erase(session);
+ pthread_mutex_unlock(&mBiDictMutex);
+ }
+ uint32_t getId(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ uint32_t ret = 0;
+ auto it = mBackwardMap.find(session);
+ if (it != mBackwardMap.end()) {
+ ret = it->second;
+ }
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ uint32_t getSession(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ uint32_t ret = 0;
+ auto it = mForwardMap.find(id);
+ if (it != mForwardMap.end()) {
+ ret = it->second;
+ }
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ T getExtById(uint32_t id) {
+ pthread_mutex_lock(&mBiDictMutex);
+ T ret;
+ memset(&ret, 0, sizeof(T));
+ uint32_t session = mForwardMap[id];
+ if (session > 0) {
+ auto it = mExtMap.find(session);
+ if (it != mExtMap.end()) {
+ ret = it->second;
+ }
+ }
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ T getExtBySession(uint32_t session) {
+ pthread_mutex_lock(&mBiDictMutex);
+ T ret;
+ memset(&ret, 0, sizeof(T));
+ auto it = mExtMap.find(session);
+ if (it != mExtMap.end()) {
+ ret = it->second;
+ }
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ std::vector<uint32_t> getAllSessions() {
+ std::vector<uint32_t> ret;
+ pthread_mutex_lock(&mBiDictMutex);
+ for (auto it = mBackwardMap.begin(); it != mBackwardMap.end(); it++) {
+ ret.push_back(it->first);
+ }
+ pthread_mutex_unlock(&mBiDictMutex);
+ return ret;
+ }
+ private:
+ pthread_mutex_t mBiDictMutex;
+ // mForwarMap mapping id->session
+ std::map<uint32_t, uint32_t> mForwardMap;
+ // mBackwardMap mapping session->id
+ std::map<uint32_t, uint32_t> mBackwardMap;
+ // mExtMap mapping session->ext
+ std::map<uint32_t, T> mExtMap;
+ };
+
+ class StartTrackingRequest : public LocationAPIRequest {
+ public:
+ StartTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t id) {
+ if (error != LOCATION_ERROR_SUCCESS) {
+ mAPI.removeSession(id);
+ }
+ mAPI.onStartTrackingCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class StopTrackingRequest : public LocationAPIRequest {
+ public:
+ StopTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t id) {
+ mAPI.onStopTrackingCb(error);
+ if (error == LOCATION_ERROR_SUCCESS) {
+ mAPI.removeSession(id);
+ }
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class UpdateTrackingOptionsRequest : public LocationAPIRequest {
+ public:
+ UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onUpdateTrackingOptionsCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class StartBatchingRequest : public LocationAPIRequest {
+ public:
+ StartBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t id) {
+ if (error != LOCATION_ERROR_SUCCESS) {
+ mAPI.removeSession(id);
+ }
+ mAPI.onStartBatchingCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class StopBatchingRequest : public LocationAPIRequest {
+ public:
+ StopBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t id) {
+ mAPI.onStopBatchingCb(error);
+ if (error == LOCATION_ERROR_SUCCESS) {
+ mAPI.removeSession(id);
+ }
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class UpdateBatchingOptionsRequest : public LocationAPIRequest {
+ public:
+ UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onUpdateBatchingOptionsCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class GetBatchedLocationsRequest : public LocationAPIRequest {
+ public:
+ GetBatchedLocationsRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onGetBatchedLocationsCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class AddGeofencesRequest : public LocationAPIRequest {
+ public:
+ AddGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ for (size_t i = 0; i < count; i++) {
+ ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
+ }
+ LOC_LOGD("%s:]Returned geofence-id: %d in add geofence", __FUNCTION__, *ids);
+ mAPI.onAddGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class RemoveGeofencesRequest : public LocationAPIRequest {
+ public:
+ RemoveGeofencesRequest(LocationAPIClientBase& API,
+ BiDict<GeofenceBreachTypeMask>* removedGeofenceBiDict) :
+ mAPI(API), mRemovedGeofenceBiDict(removedGeofenceBiDict) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ if (nullptr != mRemovedGeofenceBiDict) {
+ uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ for (size_t i = 0; i < count; i++) {
+ ids[i] = mRemovedGeofenceBiDict->getId(sessions[i]);
+ }
+ LOC_LOGD("%s:]Returned geofence-id: %d in remove geofence", __FUNCTION__, *ids);
+ mAPI.onRemoveGeofencesCb(count, errors, ids);
+ free(ids);
+ delete(mRemovedGeofenceBiDict);
+ } else {
+ LOC_LOGE("%s:%d] Unable to access removed geofences data.", __FUNCTION__, __LINE__);
+ }
+ }
+ LocationAPIClientBase& mAPI;
+ BiDict<GeofenceBreachTypeMask>* mRemovedGeofenceBiDict;
+ };
+
+ class ModifyGeofencesRequest : public LocationAPIRequest {
+ public:
+ ModifyGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ for (size_t i = 0; i < count; i++) {
+ ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
+ }
+ mAPI.onModifyGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class PauseGeofencesRequest : public LocationAPIRequest {
+ public:
+ PauseGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ for (size_t i = 0; i < count; i++) {
+ ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
+ }
+ mAPI.onPauseGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class ResumeGeofencesRequest : public LocationAPIRequest {
+ public:
+ ResumeGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
+ uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
+ for (size_t i = 0; i < count; i++) {
+ ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
+ }
+ mAPI.onResumeGeofencesCb(count, errors, ids);
+ free(ids);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+ class GnssNiResponseRequest : public LocationAPIRequest {
+ public:
+ GnssNiResponseRequest(LocationAPIClientBase& API) : mAPI(API) {}
+ inline void onResponse(LocationError error, uint32_t /*id*/) {
+ mAPI.onGnssNiResponseCb(error);
+ }
+ LocationAPIClientBase& mAPI;
+ };
+
+private:
+ pthread_mutex_t mMutex;
+
+ geofenceBreachCallback mGeofenceBreachCallback;
+ batchingStatusCallback mBatchingStatusCallback;
+
+ LocationAPI* mLocationAPI;
+
+ RequestQueue mRequestQueues[REQUEST_MAX];
+ BiDict<GeofenceBreachTypeMask> mGeofenceBiDict;
+ BiDict<SessionEntity> mSessionBiDict;
+ int32_t mBatchSize;
+ bool mTracking;
+};
+
+#endif /* LOCATION_API_CLINET_BASE_H */
diff --git a/gps/location/LocationDataTypes.h b/gps/location/LocationDataTypes.h
new file mode 100644
index 0000000..b85464a
--- /dev/null
+++ b/gps/location/LocationDataTypes.h
@@ -0,0 +1,2070 @@
+/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LOCATIONDATATYPES_H
+#define LOCATIONDATATYPES_H
+
+#include <vector>
+#include <stdint.h>
+#include <functional>
+#include <list>
+#include <string.h>
+#include <string>
+
+#define GNSS_NI_REQUESTOR_MAX (256)
+#define GNSS_NI_MESSAGE_ID_MAX (2048)
+#define GNSS_SV_MAX (128)
+#define GNSS_MEASUREMENTS_MAX (128)
+#define GNSS_UTC_TIME_OFFSET (3657)
+
+#define GNSS_BUGREPORT_GPS_MIN (1)
+#define GNSS_BUGREPORT_SBAS_MIN (120)
+#define GNSS_BUGREPORT_GLO_MIN (1)
+#define GNSS_BUGREPORT_QZSS_MIN (193)
+#define GNSS_BUGREPORT_BDS_MIN (1)
+#define GNSS_BUGREPORT_GAL_MIN (1)
+#define GNSS_BUGREPORT_NAVIC_MIN (1)
+
+#define GNSS_MAX_NAME_LENGTH (8)
+
+typedef enum {
+ LOCATION_ERROR_SUCCESS = 0,
+ LOCATION_ERROR_GENERAL_FAILURE,
+ LOCATION_ERROR_CALLBACK_MISSING,
+ LOCATION_ERROR_INVALID_PARAMETER,
+ LOCATION_ERROR_ID_EXISTS,
+ LOCATION_ERROR_ID_UNKNOWN,
+ LOCATION_ERROR_ALREADY_STARTED,
+ LOCATION_ERROR_GEOFENCES_AT_MAX,
+ LOCATION_ERROR_NOT_SUPPORTED,
+ LOCATION_ERROR_TIMEOUT,
+} LocationError;
+
+// Flags to indicate which values are valid in a Location
+typedef uint16_t LocationFlagsMask;
+typedef enum {
+ LOCATION_HAS_LAT_LONG_BIT = (1<<0), // location has valid latitude and longitude
+ LOCATION_HAS_ALTITUDE_BIT = (1<<1), // location has valid altitude
+ LOCATION_HAS_SPEED_BIT = (1<<2), // location has valid speed
+ LOCATION_HAS_BEARING_BIT = (1<<3), // location has valid bearing
+ LOCATION_HAS_ACCURACY_BIT = (1<<4), // location has valid accuracy
+ LOCATION_HAS_VERTICAL_ACCURACY_BIT = (1<<5), // location has valid vertical accuracy
+ LOCATION_HAS_SPEED_ACCURACY_BIT = (1<<6), // location has valid speed accuracy
+ LOCATION_HAS_BEARING_ACCURACY_BIT = (1<<7), // location has valid bearing accuracy
+ LOCATION_HAS_SPOOF_MASK = (1<<8), // location has valid spoof mask
+ LOCATION_HAS_ELAPSED_REAL_TIME = (1<<9), // location has valid elapsed real time
+ LOCATION_HAS_CONFORMITY_INDEX_BIT = (1<<10), // location has valid conformity index
+} LocationFlagsBits;
+
+typedef uint16_t LocationTechnologyMask;
+// mask indicating location calculations including...
+typedef enum {
+ LOCATION_TECHNOLOGY_GNSS_BIT = (1<<0), // using GNSS
+ LOCATION_TECHNOLOGY_CELL_BIT = (1<<1), // using Cell
+ LOCATION_TECHNOLOGY_WIFI_BIT = (1<<2), // using WiFi
+ LOCATION_TECHNOLOGY_SENSORS_BIT = (1<<3), // using Sensors
+ LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT = (1<<4), // using reference location
+ LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT = (1<<5), // using CPI
+ LOCATION_TECHNOLOGY_AFLT_BIT = (1<<6), // AFLT
+ LOCATION_TECHNOLOGY_HYBRID_BIT = (1<<7), // HYBRID
+ LOCATION_TECHNOLOGY_PPE_BIT = (1<<8), // PPE
+ LOCATION_TECHNOLOGY_VEH_BIT = (1<<9), // using vehicular data
+ LOCATION_TECHNOLOGY_VIS_BIT = (1<<10), // using visual data
+ LOCATION_TECHNOLOGY_DGNSS_BIT = (1<<11), // DGNSS
+} LocationTechnologyBits;
+
+typedef uint32_t LocationSpoofMask;
+typedef enum {
+ LOCATION_POSTION_SPOOFED = (1<<0), // location position spoofed
+ LOCATION_TIME_SPOOFED = (1<<1), // location time spoofed
+ LOCATION_NAVIGATION_DATA_SPOOFED = (1<<2), // location navigation data spoofed
+} LocationSpoofBits;
+
+typedef enum {
+ LOCATION_RELIABILITY_NOT_SET = 0,
+ LOCATION_RELIABILITY_VERY_LOW,
+ LOCATION_RELIABILITY_LOW,
+ LOCATION_RELIABILITY_MEDIUM,
+ LOCATION_RELIABILITY_HIGH,
+} LocationReliability;
+
+typedef uint32_t GnssLocationNavSolutionMask;
+typedef enum {
+ // SBAS ionospheric correction is used
+ LOCATION_SBAS_CORRECTION_IONO_BIT = (1<<0),
+ // SBAS fast correction is used
+ LOCATION_SBAS_CORRECTION_FAST_BIT = (1<<1),
+ // SBAS long-tem correction is used
+ LOCATION_SBAS_CORRECTION_LONG_BIT = (1<<2),
+ // SBAS integrity information is used
+ LOCATION_SBAS_INTEGRITY_BIT = (1<<3),
+ // Position Report is DGNSS corrected
+ LOCATION_NAV_CORRECTION_DGNSS_BIT = (1<<4),
+ // Position Report is RTK corrected
+ LOCATION_NAV_CORRECTION_RTK_BIT = (1<<5),
+ // Position Report is PPP corrected
+ LOCATION_NAV_CORRECTION_PPP_BIT = (1<<6),
+ // Posiiton Report is RTF fixed corrected
+ LOCATION_NAV_CORRECTION_RTK_FIXED_BIT = (1<<7),
+ // Position report is computed with only SBAS corrected SVs.
+ LOCATION_NAV_CORRECTION_ONLY_SBAS_CORRECTED_SV_USED_BIT = (1<<8)
+} GnssLocationNavSolutionBits;
+
+typedef uint32_t GnssLocationPosDataMask;
+typedef enum {
+ LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT = (1<<0), // Navigation data has Forward Acceleration
+ LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT = (1<<1), // Navigation data has Sideward Acceleration
+ LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT = (1<<2), // Navigation data has Vertical Acceleration
+ LOCATION_NAV_DATA_HAS_YAW_RATE_BIT = (1<<3), // Navigation data has Heading Rate
+ LOCATION_NAV_DATA_HAS_PITCH_BIT = (1<<4), // Navigation data has Body pitch
+ // Navigation data has Forward Acceleration uncertainty
+ LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT = (1<<5),
+ // Navigation data has Sideward Acceleration uncertainty
+ LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT = (1<<6),
+ // Navigation data has Vertical Acceleration uncertainty
+ LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT = (1<<7),
+ // Navigation data has Heading Rate uncertainty
+ LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT = (1<<8),
+ // Navigation data has Body pitch uncertainty
+ LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT = (1<<9)
+} GnssLocationPosDataBits;
+
+typedef uint32_t GnssLocationPosDataMaskExt;
+typedef enum {
+ // Navigation data has pitch rate
+ LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT = (1<<0),
+ // Navigation data has body pitch rate uncertainty
+ LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT = (1<<1),
+ // Navigation data has body roll
+ LOCATION_NAV_DATA_HAS_ROLL_BIT = (1<<2),
+ // Navigation data has body roll uncertainty
+ LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT = (1<<3),
+ // Navigation data has body rate roll
+ LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT = (1<<4),
+ // Navigation data has body roll rate uncertainty
+ LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT = (1<<5),
+ // Navigation data has body yaw
+ LOCATION_NAV_DATA_HAS_YAW_BIT = (1<<6),
+ // Navigation data has body roll uncertainty
+ LOCATION_NAV_DATA_HAS_YAW_UNC_BIT = (1<<7)
+} GnssLocationPosDataBitsExt;
+
+typedef uint64_t GnssLocationInfoFlagMask;
+typedef enum {
+ GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT = (1<<0), // altitude mean sea level
+ GNSS_LOCATION_INFO_DOP_BIT = (1<<1), // pdop, hdop, and vdop
+ GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT = (1<<2), // magnetic deviation
+ GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<3), // horizontal reliability
+ GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<4), // vertical reliability
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // elipsode semi major
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // elipsode semi minor
+ GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<7), // accuracy elipsode azimuth
+ GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT = (1<<8), // svUsedInPosition,
+ // numOfMeasReceived
+ // and measUsageInfo
+ GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT = (1<<9), // navSolutionMask
+ GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT = (1<<10), // LocSvInfoSource
+ GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT = (1<<11), // position dynamics data &
+ // Position Dynamics Ext
+ GNSS_LOCATION_INFO_EXT_DOP_BIT = (1<<12), // gdop, tdop
+ GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT = (1<<13), // North standard deviation
+ GNSS_LOCATION_INFO_EAST_STD_DEV_BIT = (1<<14), // East standard deviation
+ GNSS_LOCATION_INFO_NORTH_VEL_BIT = (1<<15), // North Velocity
+ GNSS_LOCATION_INFO_EAST_VEL_BIT = (1<<16), // East Velocity
+ GNSS_LOCATION_INFO_UP_VEL_BIT = (1<<17), // Up Velocity
+ GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT = (1<<18), // North Velocity Uncertainty
+ GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT = (1<<19), // East Velocity Uncertainty
+ GNSS_LOCATION_INFO_UP_VEL_UNC_BIT = (1<<20), // Up Velocity Uncertainty
+ GNSS_LOCATION_INFO_LEAP_SECONDS_BIT = (1<<21), // leap seconds
+ GNSS_LOCATION_INFO_TIME_UNC_BIT = (1<<22), // time uncertainty
+ GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT = (1<<23), // number of SV used in position
+ GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT = (1<<24), // sensor cal confidence
+ GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT = (1<<25), // sensor cal status
+ GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT = (1<<26), // output engine type
+ GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT = (1<<27), // output engine mask
+ GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT = (1<<28), // conformity index
+ GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT = (1<<29), // VRP-based lat/long/alt
+ GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT = (1<<30), // VRP-based east/north/up vel
+ GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT = (1ULL<<31), // Valid DR solution status
+ GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT = (1ULL<<32), // Valid altitude assumed
+ GNSS_LOCATION_INFO_SESSION_STATUS_BIT = (1ULL<<33), // session status
+} GnssLocationInfoFlagBits;
+
+typedef enum {
+ GEOFENCE_BREACH_ENTER = 0,
+ GEOFENCE_BREACH_EXIT,
+ GEOFENCE_BREACH_DWELL_IN,
+ GEOFENCE_BREACH_DWELL_OUT,
+ GEOFENCE_BREACH_UNKNOWN,
+} GeofenceBreachType;
+
+typedef uint16_t GeofenceBreachTypeMask;
+typedef enum {
+ GEOFENCE_BREACH_ENTER_BIT = (1<<0),
+ GEOFENCE_BREACH_EXIT_BIT = (1<<1),
+ GEOFENCE_BREACH_DWELL_IN_BIT = (1<<2),
+ GEOFENCE_BREACH_DWELL_OUT_BIT = (1<<3),
+} GeofenceBreachTypeBits;
+
+typedef enum {
+ GEOFENCE_STATUS_AVAILABILE_NO = 0,
+ GEOFENCE_STATUS_AVAILABILE_YES,
+} GeofenceStatusAvailable;
+
+// Set of masks for Modem and QWES capabilities.
+typedef uint64_t LocationCapabilitiesMask;
+typedef enum {
+ // supports startTracking API with minInterval param
+ LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT = (1<<0),
+ // supports startBatching API with minInterval param
+ LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT = (1<<1),
+ // supports startTracking API with minDistance param
+ LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT = (1<<2),
+ // supports startBatching API with minDistance param
+ LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT = (1<<3),
+ // supports addGeofences API
+ LOCATION_CAPABILITIES_GEOFENCE_BIT = (1<<4),
+ // supports GnssMeasurementsCallback
+ LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT = (1<<5),
+ // supports startTracking/startBatching API with LocationOptions.mode of MSB (Ms Based)
+ LOCATION_CAPABILITIES_GNSS_MSB_BIT = (1<<6),
+ // supports startTracking/startBatching API with LocationOptions.mode of MSA (MS Assisted)
+ LOCATION_CAPABILITIES_GNSS_MSA_BIT = (1<<7),
+ // supports debug nmea sentences in the debugNmeaCallback
+ LOCATION_CAPABILITIES_DEBUG_NMEA_BIT = (1<<8),
+ // support outdoor trip batching
+ LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT = (1<<9),
+ // support constellation enablement
+ LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT = (1<<10),
+ // support agpm
+ LOCATION_CAPABILITIES_AGPM_BIT = (1<<11),
+ // support location privacy
+ LOCATION_CAPABILITIES_PRIVACY_BIT = (1<<12),
+ // support measurement corrections
+ LOCATION_CAPABILITIES_MEASUREMENTS_CORRECTION_BIT = (1<<13),
+ // support Robust Location
+ LOCATION_CAPABILITIES_CONFORMITY_INDEX_BIT = (1<<14),
+ // support precise location edgnss
+ LOCATION_CAPABILITIES_EDGNSS_BIT = (1<<15),
+ // Modem supports Carrier Phase for Precise Positioning
+ // Measurement Engine (PPME).
+ LOCATION_CAPABILITIES_QWES_CARRIER_PHASE_BIT = (1<<16),
+ // Modem supports SV Polynomial for tightly coupled external
+ // DR support. This is a Standalone Feature.
+ LOCATION_CAPABILITIES_QWES_SV_POLYNOMIAL_BIT = (1<<17),
+ // Modem supports SV Ephemeris for tightly coupled external
+ // PPE engines. This is a Standalone Feature.
+ LOCATION_CAPABILITIES_QWES_SV_EPHEMERIS_BIT = (1<<18),
+ // Modem supports GNSS Single Frequency feature. This is a
+ // Standalone Feature.
+ LOCATION_CAPABILITIES_QWES_GNSS_SINGLE_FREQUENCY = (1<<19),
+ // Modem supports GNSS Multi Frequency feature. Multi Frequency
+ // enables Single frequency also.
+ LOCATION_CAPABILITIES_QWES_GNSS_MULTI_FREQUENCY = (1<<20),
+ // This mask indicates VPe license bundle is enabled. VEPP
+ // bundle include Carrier Phase and SV Polynomial features.
+ LOCATION_CAPABILITIES_QWES_VPE = (1<<21),
+ // This mask indicates support for CV2X Location basic features.
+ // This bundle includes features for GTS Time & Freq, C-TUNC
+ // (Constrained Time uncertainity.
+ LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_BASIC = (1<<22),
+ // This mask indicates support for CV2X Location premium features.
+ // This bundle includes features for CV2X Location Basic features,
+ // QDR3 feature, and PACE. (Position Assisted Clock Estimator.
+ LOCATION_CAPABILITIES_QWES_CV2X_LOCATION_PREMIUM = (1<<23),
+ // This mask indicates that PPE (Precise Positioning Engine)
+ // library is enabled or Precise Positioning Framework (PPF)
+ // is available. This bundle includes features for Carrier
+ // Phase and SV Ephermeris.
+ LOCATION_CAPABILITIES_QWES_PPE = (1<<24),
+ // This mask indicates QDR2_C license bundle is enabled. This
+ // bundle includes features for SV Polynomial.
+ LOCATION_CAPABILITIES_QWES_QDR2 = (1<<25),
+ // This mask indicates QDR3_C license bundle is enabled. This
+ // bundle includes features for SV Polynomial.
+ LOCATION_CAPABILITIES_QWES_QDR3 = (1<<26),
+} LocationCapabilitiesBits;
+
+typedef uint8_t LocationQwesFeatureType;
+typedef enum {
+ // Modem supports Carrier Phase for Precise Positioning
+ // Measurement Engine (PPME).
+ LOCATION_QWES_FEATURE_TYPE_CARRIER_PHASE = 1,
+ // Modem supports SV Polynomial for tightly coupled external
+ // DR support. This is a Standalone Feature.
+ LOCATION_QWES_FEATURE_TYPE_SV_POLYNOMIAL,
+ // Modem supports SV Ephemeris for tightly coupled external
+ // PPE support. This is a Standalone Feature.
+ LOCATION_QWES_FEATURE_TYPE_SV_EPH,
+ // Modem supports GNSS Single Frequency feature. This is a
+ // Standalone Feature.
+ LOCATION_QWES_FEATURE_TYPE_GNSS_SINGLE_FREQUENCY,
+ // Modem supports GNSS Multi Frequency feature. Multi Frequency
+ // enables Single frequency also.
+ LOCATION_QWES_FEATURE_TYPE_GNSS_MULTI_FREQUENCY,
+ // This indicates Time and Frequency status.
+ LOCATION_QWES_FEATURE_TYPE_TIME_FREQUENCY,
+ // This indicates Time Uncertainty status.
+ LOCATION_QWES_FEATURE_TYPE_TIME_UNCERTAINTY,
+ // This indicates Clock Estimate status.
+ LOCATION_QWES_FEATURE_TYPE_CLOCK_ESTIMATE,
+ // This mask indicates that PPE (Precise Positioning Engine)
+ // library is enabled or Precise Positioning Framework (PPF)
+ // is available. This bundle includes features for Carrier
+ // Phase and SV Ephermeris.
+ LOCATION_QWES_FEATURE_TYPE_PPE,
+ // This indicates QDR2_C license bundle is enabled. This
+ // bundle includes features for SV Polynomial.
+ LOCATION_QWES_FEATURE_TYPE_QDR2,
+ // This indicates QDR3_C license bundle is enabled. This
+ // bundle includes features for SV Polynomial.
+ LOCATION_QWES_FEATURE_TYPE_QDR3,
+ // This indicates VEPP license bundle is enabled. VEPP
+ // bundle include Carrier Phase and SV Polynomial features.
+ LOCATION_QWES_FEATURE_TYPE_VPE,
+ // Max value
+ LOCATION_QWES_FEATURE_TYPE_MAX
+} LocationQwesFeatureTypes;
+
+typedef enum {
+ LOCATION_TECHNOLOGY_TYPE_GNSS = 0,
+} LocationTechnologyType;
+
+// Configures how GPS is locked when GPS is disabled (through GnssDisable)
+enum {
+ GNSS_CONFIG_GPS_LOCK_NONE = 0, // gps is not locked when GPS is disabled (GnssDisable)
+ GNSS_CONFIG_GPS_LOCK_MO, // gps mobile originated (MO) is locked when GPS is disabled
+ GNSS_CONFIG_GPS_LOCK_NI, // gps network initiated (NI) is locked when GPS is disabled
+ GNSS_CONFIG_GPS_LOCK_MO_AND_NI,// gps MO and NI is locked when GPS is disabled
+};
+typedef int32_t GnssConfigGpsLock;
+
+// SUPL version
+typedef enum {
+ GNSS_CONFIG_SUPL_VERSION_1_0_0 = 1,
+ GNSS_CONFIG_SUPL_VERSION_2_0_0,
+ GNSS_CONFIG_SUPL_VERSION_2_0_2,
+ GNSS_CONFIG_SUPL_VERSION_2_0_4,
+} GnssConfigSuplVersion;
+
+// LTE Positioning Profile
+typedef uint16_t GnssConfigLppProfileMask;
+typedef enum {
+ GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0, // RRLP on LTE (Default)
+ GNSS_CONFIG_LPP_PROFILE_USER_PLANE_BIT = (1<<0), // LPP User Plane (UP) on LTE
+ GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_BIT = (1<<1), // LPP_Control_Plane (CP)
+ GNSS_CONFIG_LPP_PROFILE_USER_PLANE_OVER_NR5G_SA_BIT = (1<<2), // LPP User Plane (UP) on LTE
+ GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE_OVER_NR5G_SA_BIT = (1<<3), // LPP_Control_Plane (CP)
+} GnssConfigLppProfileBits;
+
+// Technology for LPPe Control Plane
+typedef uint16_t GnssConfigLppeControlPlaneMask;
+typedef enum {
+ GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT = (1<<0), // DBH
+ GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT = (1<<1), // WLAN_AP_MEASUREMENTS
+ GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT = (1<<2), // SRN_AP_MEASUREMENTS
+ GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT = (1<<3),
+ // SENSOR_BARO_MEASUREMENTS
+} GnssConfigLppeControlPlaneBits;
+
+// Technology for LPPe User Plane
+typedef uint16_t GnssConfigLppeUserPlaneMask;
+typedef enum {
+ GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT = (1<<0), // DBH
+ GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT = (1<<1), // WLAN_AP_MEASUREMENTS
+ GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT = (1<<2), // SRN_AP_MEASUREMENTS
+ GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT = (1<<3),
+ // SENSOR_BARO_MEASUREMENTS
+} GnssConfigLppeUserPlaneBits;
+
+// Positioning Protocol on A-GLONASS system
+typedef uint16_t GnssConfigAGlonassPositionProtocolMask;
+typedef enum {
+ GNSS_CONFIG_RRC_CONTROL_PLANE_BIT = (1<<0), // RRC Control Plane
+ GNSS_CONFIG_RRLP_USER_PLANE_BIT = (1<<1), // RRLP User Plane
+ GNSS_CONFIG_LLP_USER_PLANE_BIT = (1<<2), // LPP User Plane
+ GNSS_CONFIG_LLP_CONTROL_PLANE_BIT = (1<<3), // LPP Control Plane
+} GnssConfigAGlonassPositionProtocolBits;
+
+typedef enum {
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO = 0,
+ GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES,
+} GnssConfigEmergencyPdnForEmergencySupl;
+
+typedef enum {
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO = 0,
+ GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES,
+} GnssConfigSuplEmergencyServices;
+
+typedef uint16_t GnssConfigSuplModeMask;
+typedef enum {
+ GNSS_CONFIG_SUPL_MODE_MSB_BIT = (1<<0),
+ GNSS_CONFIG_SUPL_MODE_MSA_BIT = (1<<1),
+} GnssConfigSuplModeBits;
+
+typedef uint32_t GnssConfigFlagsMask;
+typedef enum {
+ GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT = (1<<0),
+ GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT = (1<<1),
+ GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT = (1<<2),
+ GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT = (1<<3),
+ GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT = (1<<4),
+ GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT = (1<<5),
+ GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT = (1<<6),
+ GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT = (1<<7),
+ GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT = (1<<8),
+ GNSS_CONFIG_FLAGS_SUPL_MODE_BIT = (1<<9),
+ GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT = (1<<10),
+ GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT = (1<<11),
+ GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT = (1<<12),
+ GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT = (1<<13),
+ GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT = (1<<14),
+ GNSS_CONFIG_FLAGS_CONSTELLATION_SECONDARY_BAND_BIT = (1<<15),
+} GnssConfigFlagsBits;
+
+typedef enum {
+ GNSS_NI_ENCODING_TYPE_NONE = 0,
+ GNSS_NI_ENCODING_TYPE_GSM_DEFAULT,
+ GNSS_NI_ENCODING_TYPE_UTF8,
+ GNSS_NI_ENCODING_TYPE_UCS2,
+} GnssNiEncodingType;
+
+typedef enum {
+ GNSS_NI_TYPE_VOICE = 0,
+ GNSS_NI_TYPE_SUPL,
+ GNSS_NI_TYPE_CONTROL_PLANE,
+ GNSS_NI_TYPE_EMERGENCY_SUPL
+} GnssNiType;
+
+typedef uint16_t GnssNiOptionsMask;
+typedef enum {
+ GNSS_NI_OPTIONS_NOTIFICATION_BIT = (1<<0),
+ GNSS_NI_OPTIONS_VERIFICATION_BIT = (1<<1),
+ GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT = (1<<2),
+} GnssNiOptionsBits;
+
+typedef enum {
+ GNSS_NI_RESPONSE_ACCEPT = 1,
+ GNSS_NI_RESPONSE_DENY,
+ GNSS_NI_RESPONSE_NO_RESPONSE,
+ GNSS_NI_RESPONSE_IGNORE,
+} GnssNiResponse;
+
+typedef enum {
+ GNSS_SV_TYPE_UNKNOWN = 0,
+ GNSS_SV_TYPE_GPS,
+ GNSS_SV_TYPE_SBAS,
+ GNSS_SV_TYPE_GLONASS,
+ GNSS_SV_TYPE_QZSS,
+ GNSS_SV_TYPE_BEIDOU,
+ GNSS_SV_TYPE_GALILEO,
+ GNSS_SV_TYPE_NAVIC,
+} GnssSvType;
+
+typedef enum {
+ GNSS_EPH_TYPE_UNKNOWN = 0,
+ GNSS_EPH_TYPE_EPHEMERIS,
+ GNSS_EPH_TYPE_ALMANAC,
+} GnssEphemerisType;
+
+typedef enum {
+ GNSS_EPH_SOURCE_UNKNOWN = 0,
+ GNSS_EPH_SOURCE_DEMODULATED,
+ GNSS_EPH_SOURCE_SUPL_PROVIDED,
+ GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED,
+ GNSS_EPH_SOURCE_LOCAL,
+} GnssEphemerisSource;
+
+typedef enum {
+ GNSS_EPH_HEALTH_UNKNOWN = 0,
+ GNSS_EPH_HEALTH_GOOD,
+ GNSS_EPH_HEALTH_BAD,
+} GnssEphemerisHealth;
+
+typedef uint16_t GnssSvOptionsMask;
+typedef enum {
+ GNSS_SV_OPTIONS_HAS_EPHEMER_BIT = (1<<0),
+ GNSS_SV_OPTIONS_HAS_ALMANAC_BIT = (1<<1),
+ GNSS_SV_OPTIONS_USED_IN_FIX_BIT = (1<<2),
+ GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT = (1<<3),
+ GNSS_SV_OPTIONS_HAS_GNSS_SIGNAL_TYPE_BIT = (1<<4)
+} GnssSvOptionsBits;
+
+typedef enum {
+ GNSS_ASSISTANCE_TYPE_SUPL = 0,
+ GNSS_ASSISTANCE_TYPE_C2K,
+ GNSS_ASSISTANCE_TYPE_SUPL_EIMS,
+ GNSS_ASSISTANCE_TYPE_SUPL_IMS,
+} GnssAssistanceType;
+
+typedef enum {
+ GNSS_SUPL_MODE_STANDALONE = 0,
+ GNSS_SUPL_MODE_MSB,
+ GNSS_SUPL_MODE_MSA,
+} GnssSuplMode;
+
+typedef enum {
+ BATCHING_MODE_ROUTINE = 0, // positions are reported when batched positions memory is full
+ BATCHING_MODE_TRIP, // positions are reported when a certain distance is covered
+ BATCHING_MODE_NO_AUTO_REPORT // no report of positions automatically, instead queried on demand
+} BatchingMode;
+
+typedef enum {
+ BATCHING_STATUS_TRIP_COMPLETED = 0,
+ BATCHING_STATUS_POSITION_AVAILABE,
+ BATCHING_STATUS_POSITION_UNAVAILABLE
+} BatchingStatus;
+
+typedef uint16_t GnssMeasurementsAdrStateMask;
+typedef enum {
+ GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_UNKNOWN = 0,
+ GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT = (1<<0),
+ GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT = (1<<1),
+ GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT = (1<<2),
+ GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT = (1<<3),
+} GnssMeasurementsAdrStateBits;
+
+typedef enum {
+ GNSS_MEASUREMENTS_CODE_TYPE_A = 0,
+ GNSS_MEASUREMENTS_CODE_TYPE_B = 1,
+ GNSS_MEASUREMENTS_CODE_TYPE_C = 2,
+ GNSS_MEASUREMENTS_CODE_TYPE_I = 3,
+ GNSS_MEASUREMENTS_CODE_TYPE_L = 4,
+ GNSS_MEASUREMENTS_CODE_TYPE_M = 5,
+ GNSS_MEASUREMENTS_CODE_TYPE_P = 6,
+ GNSS_MEASUREMENTS_CODE_TYPE_Q = 7,
+ GNSS_MEASUREMENTS_CODE_TYPE_S = 8,
+ GNSS_MEASUREMENTS_CODE_TYPE_W = 9,
+ GNSS_MEASUREMENTS_CODE_TYPE_X = 10,
+ GNSS_MEASUREMENTS_CODE_TYPE_Y = 11,
+ GNSS_MEASUREMENTS_CODE_TYPE_Z = 12,
+ GNSS_MEASUREMENTS_CODE_TYPE_N = 13,
+ GNSS_MEASUREMENTS_CODE_TYPE_OTHER = 255,
+} GnssMeasurementsCodeType;
+
+typedef uint32_t GnssMeasurementsDataFlagsMask;
+typedef enum {
+ GNSS_MEASUREMENTS_DATA_SV_ID_BIT = (1<<0),
+ GNSS_MEASUREMENTS_DATA_SV_TYPE_BIT = (1<<1),
+ GNSS_MEASUREMENTS_DATA_STATE_BIT = (1<<2),
+ GNSS_MEASUREMENTS_DATA_RECEIVED_SV_TIME_BIT = (1<<3),
+ GNSS_MEASUREMENTS_DATA_RECEIVED_SV_TIME_UNCERTAINTY_BIT = (1<<4),
+ GNSS_MEASUREMENTS_DATA_CARRIER_TO_NOISE_BIT = (1<<5),
+ GNSS_MEASUREMENTS_DATA_PSEUDORANGE_RATE_BIT = (1<<6),
+ GNSS_MEASUREMENTS_DATA_PSEUDORANGE_RATE_UNCERTAINTY_BIT = (1<<7),
+ GNSS_MEASUREMENTS_DATA_ADR_STATE_BIT = (1<<8),
+ GNSS_MEASUREMENTS_DATA_ADR_BIT = (1<<9),
+ GNSS_MEASUREMENTS_DATA_ADR_UNCERTAINTY_BIT = (1<<10),
+ GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT = (1<<11),
+ GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT = (1<<12),
+ GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT = (1<<13),
+ GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT = (1<<14),
+ GNSS_MEASUREMENTS_DATA_MULTIPATH_INDICATOR_BIT = (1<<15),
+ GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT = (1<<16),
+ GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT = (1<<17),
+ GNSS_MEASUREMENTS_DATA_FULL_ISB_BIT = (1<<18),
+ GNSS_MEASUREMENTS_DATA_FULL_ISB_UNCERTAINTY_BIT = (1<<19),
+ GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_BIT = (1<<20),
+ GNSS_MEASUREMENTS_DATA_SATELLITE_ISB_UNCERTAINTY_BIT = (1<<21),
+ GNSS_MEASUREMENTS_DATA_CYCLE_SLIP_COUNT_BIT = (1<<22),
+} GnssMeasurementsDataFlagsBits;
+
+typedef uint32_t GnssMeasurementsStateMask;
+typedef enum {
+ GNSS_MEASUREMENTS_STATE_UNKNOWN_BIT = 0,
+ GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT = (1<<0),
+ GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT = (1<<1),
+ GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT = (1<<2),
+ GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT = (1<<3),
+ GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT = (1<<4),
+ GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT = (1<<5),
+ GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT = (1<<6),
+ GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT = (1<<7),
+ GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT = (1<<8),
+ GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT = (1<<9),
+ GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT = (1<<10),
+ GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT = (1<<11),
+ GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT = (1<<12),
+ GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT = (1<<13),
+ GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT = (1<<14),
+ GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT = (1<<15),
+ GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT = (1<<16),
+} GnssMeasurementsStateBits;
+
+typedef uint16_t GnssSingleSatCorrectionMask;
+typedef enum {
+ GNSS_MEAS_CORR_UNKNOWN_BIT = 0,
+ GNSS_MEAS_CORR_HAS_SAT_IS_LOS_PROBABILITY_BIT = (1 << 0),
+ GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_BIT = (1 << 1),
+ GNSS_MEAS_CORR_HAS_EXCESS_PATH_LENGTH_UNC_BIT = (1 << 2),
+ GNSS_MEAS_CORR_HAS_REFLECTING_PLANE_BIT = (1 << 3),
+} GnssSingleSatCorrectionBits;
+
+typedef enum {
+ GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_UNKNOWN = 0,
+ GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT,
+ GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT,
+} GnssMeasurementsMultipathIndicator;
+
+typedef uint32_t GnssMeasurementsClockFlagsMask;
+typedef enum {
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT = (1<<0),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_BIT = (1<<1),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT = (1<<2),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT = (1<<3),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT = (1<<4),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT = (1<<5),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT = (1<<6),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT = (1<<7),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_HW_CLOCK_DISCONTINUITY_COUNT_BIT = (1<<8),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT = (1<<9),
+} GnssMeasurementsClockFlagsBits;
+
+typedef uint32_t GnssAidingDataSvMask;
+typedef enum {
+ GNSS_AIDING_DATA_SV_EPHEMERIS_BIT = (1<<0), // ephemeris
+ GNSS_AIDING_DATA_SV_ALMANAC_BIT = (1<<1), // almanac
+ GNSS_AIDING_DATA_SV_HEALTH_BIT = (1<<2), // health
+ GNSS_AIDING_DATA_SV_DIRECTION_BIT = (1<<3), // direction
+ GNSS_AIDING_DATA_SV_STEER_BIT = (1<<4), // steer
+ GNSS_AIDING_DATA_SV_ALMANAC_CORR_BIT = (1<<5), // almanac correction
+ GNSS_AIDING_DATA_SV_BLACKLIST_BIT = (1<<6), // blacklist SVs
+ GNSS_AIDING_DATA_SV_SA_DATA_BIT = (1<<7), // sensitivity assistance data
+ GNSS_AIDING_DATA_SV_NO_EXIST_BIT = (1<<8), // SV does not exist
+ GNSS_AIDING_DATA_SV_IONOSPHERE_BIT = (1<<9), // ionosphere correction
+ GNSS_AIDING_DATA_SV_TIME_BIT = (1<<10),// reset satellite time
+ GNSS_AIDING_DATA_SV_MB_DATA = (1<<11),// delete multiband data
+ GNSS_AIDING_DATA_SV_POLY_BIT = (1<<12),// poly
+} GnssAidingDataSvBits;
+
+typedef uint32_t GnssAidingDataSvTypeMask;
+typedef enum {
+ GNSS_AIDING_DATA_SV_TYPE_GPS_BIT = (1<<0),
+ GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT = (1<<1),
+ GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT = (1<<2),
+ GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT = (1<<3),
+ GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT = (1<<4),
+ GNSS_AIDING_DATA_SV_TYPE_NAVIC_BIT = (1<<5),
+ GNSS_AIDING_DATA_SV_TYPE_MAX = (1<<6),
+} GnssAidingDataSvTypeBits;
+#define GNSS_AIDING_DATA_SV_TYPE_MASK_ALL (GNSS_AIDING_DATA_SV_TYPE_MAX-1)
+
+/* Gnss constellation type mask */
+typedef uint16_t GnssConstellationTypeMask;
+typedef enum {
+ GNSS_CONSTELLATION_TYPE_GPS_BIT = (1<<0),
+ GNSS_CONSTELLATION_TYPE_GLONASS_BIT = (1<<1),
+ GNSS_CONSTELLATION_TYPE_QZSS_BIT = (1<<2),
+ GNSS_CONSTELLATION_TYPE_BEIDOU_BIT = (1<<3),
+ GNSS_CONSTELLATION_TYPE_GALILEO_BIT = (1<<4),
+ GNSS_CONSTELLATION_TYPE_SBAS_BIT = (1<<5),
+ GNSS_CONSTELLATION_TYPE_NAVIC_BIT = (1<<6),
+} GnssConstellationTypeBits;
+
+#define GNSS_CONSTELLATION_TYPE_MASK_ALL\
+ (GNSS_CONSTELLATION_TYPE_GPS_BIT | GNSS_CONSTELLATION_TYPE_GLONASS_BIT |\
+ GNSS_CONSTELLATION_TYPE_QZSS_BIT | GNSS_CONSTELLATION_TYPE_BEIDOU_BIT |\
+ GNSS_CONSTELLATION_TYPE_GALILEO_BIT | GNSS_CONSTELLATION_TYPE_SBAS_BIT |\
+ GNSS_CONSTELLATION_TYPE_NAVIC_BIT)
+
+/** GNSS Signal Type and RF Band */
+typedef uint32_t GnssSignalTypeMask;
+typedef enum {
+ /** GPS L1CA Signal */
+ GNSS_SIGNAL_GPS_L1CA = (1<<0),
+ /** GPS L1C Signal */
+ GNSS_SIGNAL_GPS_L1C = (1<<1),
+ /** GPS L2 RF Band */
+ GNSS_SIGNAL_GPS_L2 = (1<<2),
+ /** GPS L5 RF Band */
+ GNSS_SIGNAL_GPS_L5 = (1<<3),
+ /** GLONASS G1 (L1OF) RF Band */
+ GNSS_SIGNAL_GLONASS_G1 = (1<<4),
+ /** GLONASS G2 (L2OF) RF Band */
+ GNSS_SIGNAL_GLONASS_G2 = (1<<5),
+ /** GALILEO E1 RF Band */
+ GNSS_SIGNAL_GALILEO_E1 = (1<<6),
+ /** GALILEO E5A RF Band */
+ GNSS_SIGNAL_GALILEO_E5A = (1<<7),
+ /** GALILEO E5B RF Band */
+ GNSS_SIGNAL_GALILEO_E5B = (1<<8),
+ /** BEIDOU B1 RF Band */
+ GNSS_SIGNAL_BEIDOU_B1 = (1<<9),
+ /** BEIDOU B2 RF Band */
+ GNSS_SIGNAL_BEIDOU_B2 = (1<<10),
+ /** QZSS L1CA RF Band */
+ GNSS_SIGNAL_QZSS_L1CA = (1<<11),
+ /** QZSS L1S RF Band */
+ GNSS_SIGNAL_QZSS_L1S = (1<<12),
+ /** QZSS L2 RF Band */
+ GNSS_SIGNAL_QZSS_L2 = (1<<13),
+ /** QZSS L5 RF Band */
+ GNSS_SIGNAL_QZSS_L5 = (1<<14),
+ /** SBAS L1 RF Band */
+ GNSS_SIGNAL_SBAS_L1 = (1<<15),
+ /** BEIDOU B1I RF Band */
+ GNSS_SIGNAL_BEIDOU_B1I = (1<<16),
+ /** BEIDOU B1C RF Band */
+ GNSS_SIGNAL_BEIDOU_B1C = (1<<17),
+ /** BEIDOU B2I RF Band */
+ GNSS_SIGNAL_BEIDOU_B2I = (1<<18),
+ /** BEIDOU B2AI RF Band */
+ GNSS_SIGNAL_BEIDOU_B2AI = (1<<19),
+ /** NAVIC L5 RF Band */
+ GNSS_SIGNAL_NAVIC_L5 = (1<<20),
+ /** BEIDOU B2A_Q RF Band */
+ GNSS_SIGNAL_BEIDOU_B2AQ = (1<<21),
+} GnssSignalTypeBits;
+
+#define GNSS_SIGNAL_TYPE_MASK_ALL\
+ (GNSS_SIGNAL_GPS_L1CA | GNSS_SIGNAL_GPS_L1C | GNSS_SIGNAL_GPS_L2 |\
+ GNSS_SIGNAL_GPS_L5| GNSS_SIGNAL_GLONASS_G1 | GNSS_SIGNAL_GLONASS_G2 |\
+ GNSS_SIGNAL_GALILEO_E1 | GNSS_SIGNAL_GALILEO_E5A | GNSS_SIGNAL_GALILEO_E5B |\
+ GNSS_SIGNAL_BEIDOU_B1I | GNSS_SIGNAL_BEIDOU_B1C | GNSS_SIGNAL_BEIDOU_B2I|\
+ GNSS_SIGNAL_BEIDOU_B2AI | GNSS_SIGNAL_QZSS_L1CA | GNSS_SIGNAL_QZSS_L1S |\
+ GNSS_SIGNAL_QZSS_L2| GNSS_SIGNAL_QZSS_L5 | GNSS_SIGNAL_SBAS_L1 |\
+ GNSS_SIGNAL_NAVIC_L5 | GNSS_SIGNAL_BEIDOU_B2AQ)
+
+typedef enum
+{
+ GNSS_LOC_SV_SYSTEM_UNKNOWN = 0,
+ /** unknown sv system. */
+ GNSS_LOC_SV_SYSTEM_MIN = 1,
+ /**< Min enum of valid SV system. */
+ GNSS_LOC_SV_SYSTEM_GPS = 1,
+ /**< GPS satellite. */
+ GNSS_LOC_SV_SYSTEM_GALILEO = 2,
+ /**< GALILEO satellite. */
+ GNSS_LOC_SV_SYSTEM_SBAS = 3,
+ /**< SBAS satellite. */
+ GNSS_LOC_SV_SYSTEM_GLONASS = 4,
+ /**< GLONASS satellite. */
+ GNSS_LOC_SV_SYSTEM_BDS = 5,
+ /**< BDS satellite. */
+ GNSS_LOC_SV_SYSTEM_QZSS = 6,
+ /**< QZSS satellite. */
+ GNSS_LOC_SV_SYSTEM_NAVIC = 7,
+ /**< NAVIC satellite. */
+ GNSS_LOC_SV_SYSTEM_MAX = 7,
+ /**< Max enum of valid SV system. */
+} Gnss_LocSvSystemEnumType;
+
+typedef enum {
+ GNSS_LOC_SIGNAL_TYPE_GPS_L1CA = 0, /**< GPS L1CA Signal */
+ GNSS_LOC_SIGNAL_TYPE_GPS_L1C = 1, /**< GPS L1C Signal */
+ GNSS_LOC_SIGNAL_TYPE_GPS_L2C_L = 2, /**< GPS L2C_L RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GPS_L5_Q = 3, /**< GPS L5_Q RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GLONASS_G1 = 4, /**< GLONASS G1 (L1OF) RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GLONASS_G2 = 5, /**< GLONASS G2 (L2OF) RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C = 6, /**< GALILEO E1_C RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GALILEO_E5A_Q = 7, /**< GALILEO E5A_Q RF Band */
+ GNSS_LOC_SIGNAL_TYPE_GALILEO_E5B_Q = 8, /**< GALILEO E5B_Q RF Band */
+ GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I = 9, /**< BEIDOU B1_I RF Band */
+ GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1C = 10, /**< BEIDOU B1C RF Band */
+ GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2_I = 11, /**< BEIDOU B2_I RF Band */
+ GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2A_I = 12, /**< BEIDOU B2A_I RF Band */
+ GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA = 13, /**< QZSS L1CA RF Band */
+ GNSS_LOC_SIGNAL_TYPE_QZSS_L1S = 14, /**< QZSS L1S RF Band */
+ GNSS_LOC_SIGNAL_TYPE_QZSS_L2C_L = 15, /**< QZSS L2C_L RF Band */
+ GNSS_LOC_SIGNAL_TYPE_QZSS_L5_Q = 16, /**< QZSS L5_Q RF Band */
+ GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA = 17, /**< SBAS L1_CA RF Band */
+ GNSS_LOC_SIGNAL_TYPE_NAVIC_L5 = 18, /**< NAVIC L5 RF Band */
+ GNSS_LOC_SIGNAL_TYPE_BEIDOU_B2A_Q = 19, /**< BEIDOU B2A_Q RF Band */
+ GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES = 20 /**< Maximum number of signal types */
+} Gnss_LocSignalEnumType;
+
+typedef uint32_t PositioningEngineMask;
+typedef enum {
+ STANDARD_POSITIONING_ENGINE = (1 << 0),
+ DEAD_RECKONING_ENGINE = (1 << 1),
+ PRECISE_POSITIONING_ENGINE = (1 << 2),
+ VP_POSITIONING_ENGINE = (1 << 3)
+} PositioningEngineBits;
+#define POSITION_ENGINE_MASK_ALL \
+ (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE| \
+ PRECISE_POSITIONING_ENGINE|VP_POSITIONING_ENGINE)
+
+/** Specify the position engine running state. <br/> */
+enum LocEngineRunState {
+ /** Request the position engine to be put into resume state.
+ * <br/> */
+ LOC_ENGINE_RUN_STATE_PAUSE = 1,
+ /** Request the position engine to be put into resume state.
+ * <br/> */
+ LOC_ENGINE_RUN_STATE_RESUME = 2,
+};
+
+typedef uint64_t GnssDataMask;
+typedef enum {
+ // Jammer Indicator is available
+ GNSS_LOC_DATA_JAMMER_IND_BIT = (1ULL << 0),
+ // AGC is available
+ GNSS_LOC_DATA_AGC_BIT = (1ULL << 1)
+} GnssDataBits;
+
+typedef uint32_t GnssSystemTimeStructTypeFlags;
+typedef enum {
+ GNSS_SYSTEM_TIME_WEEK_VALID = (1 << 0),
+ GNSS_SYSTEM_TIME_WEEK_MS_VALID = (1 << 1),
+ GNSS_SYSTEM_CLK_TIME_BIAS_VALID = (1 << 2),
+ GNSS_SYSTEM_CLK_TIME_BIAS_UNC_VALID = (1 << 3),
+ GNSS_SYSTEM_REF_FCOUNT_VALID = (1 << 4),
+ GNSS_SYSTEM_NUM_CLOCK_RESETS_VALID = (1 << 5)
+} GnssSystemTimeTypeBits;
+
+typedef uint32_t GnssGloTimeStructTypeFlags;
+typedef enum {
+ GNSS_CLO_DAYS_VALID = (1 << 0),
+ GNSS_GLO_MSEC_VALID = (1 << 1),
+ GNSS_GLO_CLK_TIME_BIAS_VALID = (1 << 2),
+ GNSS_GLO_CLK_TIME_BIAS_UNC_VALID = (1 << 3),
+ GNSS_GLO_REF_FCOUNT_VALID = (1 << 4),
+ GNSS_GLO_NUM_CLOCK_RESETS_VALID = (1 << 5),
+ GNSS_GLO_FOUR_YEAR_VALID = (1 << 6)
+} GnssGloTimeTypeBits;
+
+typedef struct {
+ GnssAidingDataSvMask svMask; // bitwise OR of GnssAidingDataSvBits
+ GnssAidingDataSvTypeMask svTypeMask; // bitwise OR of GnssAidingDataSvTypeBits
+} GnssAidingDataSv;
+
+typedef uint32_t GnssAidingDataCommonMask;
+typedef enum {
+ GNSS_AIDING_DATA_COMMON_POSITION_BIT = (1<<0), // position estimate
+ GNSS_AIDING_DATA_COMMON_TIME_BIT = (1<<1), // reset all clock values
+ GNSS_AIDING_DATA_COMMON_UTC_BIT = (1<<2), // UTC estimate
+ GNSS_AIDING_DATA_COMMON_RTI_BIT = (1<<3), // RTI
+ GNSS_AIDING_DATA_COMMON_FREQ_BIAS_EST_BIT = (1<<4), // frequency bias estimate
+ GNSS_AIDING_DATA_COMMON_CELLDB_BIT = (1<<5), // all celldb info
+} GnssAidingDataCommonBits;
+
+typedef struct {
+ GnssAidingDataCommonMask mask; // bitwise OR of GnssAidingDataCommonBits
+} GnssAidingDataCommon;
+
+typedef uint32_t DrEngineAidingDataMask;
+typedef enum {
+ DR_ENGINE_AIDING_DATA_CALIBRATION_BIT = (1<<0), // Calibration data for DRE engine
+} DrEngineAidingDataBits;
+
+typedef struct {
+ bool deleteAll; // if true, delete all aiding data and ignore other params
+ GnssAidingDataSv sv; // SV specific aiding data
+ GnssAidingDataCommon common; // common aiding data
+ DrEngineAidingDataMask dreAidingDataMask;// aiding data mask for dr engine
+ PositioningEngineMask posEngineMask; // engines to perform the delete operation on.
+} GnssAidingData;
+
+typedef uint16_t DrCalibrationStatusMask;
+typedef enum {
+ // Indicate that roll calibration is needed. Need to take more turns on level ground
+ DR_ROLL_CALIBRATION_NEEDED = (1<<0),
+ // Indicate that pitch calibration is needed. Need to take more turns on level ground
+ DR_PITCH_CALIBRATION_NEEDED = (1<<1),
+ // Indicate that yaw calibration is needed. Need to accelerate in a straight line
+ DR_YAW_CALIBRATION_NEEDED = (1<<2),
+ // Indicate that odo calibration is needed. Need to accelerate in a straight line
+ DR_ODO_CALIBRATION_NEEDED = (1<<3),
+ // Indicate that gyro calibration is needed. Need to take more turns on level ground
+ DR_GYRO_CALIBRATION_NEEDED = (1<<4)
+} DrCalibrationStatusBits;
+
+typedef struct {
+ uint32_t size; // set to sizeof(Location)
+ LocationFlagsMask flags; // bitwise OR of LocationFlagsBits to mark which params are valid
+ uint64_t timestamp; // UTC timestamp for location fix, milliseconds since January 1, 1970
+ double latitude; // in degrees
+ double longitude; // in degrees
+ double altitude; // in meters above the WGS 84 reference ellipsoid
+ float speed; // in meters per second
+ float bearing; // in degrees; range [0, 360)
+ float accuracy; // in meters
+ float verticalAccuracy; // in meters
+ float speedAccuracy; // in meters/second
+ float bearingAccuracy; // in degrees (0 to 359.999)
+ float conformityIndex; // in range [0, 1]
+ LocationTechnologyMask techMask;
+ LocationSpoofMask spoofMask;
+ uint64_t elapsedRealTime; // in ns
+ uint64_t elapsedRealTimeUnc; // in ns
+} Location;
+
+typedef enum {
+ LOC_REQ_ENGINE_FUSED_BIT = (1<<0),
+ LOC_REQ_ENGINE_SPE_BIT = (1<<1),
+ LOC_REQ_ENGINE_PPE_BIT = (1<<2),
+ LOC_REQ_ENGINE_VPE_BIT = (1<<3)
+} LocReqEngineTypeMask;
+
+typedef enum {
+ LOC_OUTPUT_ENGINE_FUSED = 0,
+ /** This is the GNSS fix from modem */
+ LOC_OUTPUT_ENGINE_SPE = 1,
+ /** This is the GNSS fix with correction PPP/RTK correction */
+ LOC_OUTPUT_ENGINE_PPE = 2,
+ LOC_OUTPUT_ENGINE_VPE = 3,
+ LOC_OUTPUT_ENGINE_COUNT,
+} LocOutputEngineType;
+
+struct LocationOptions {
+ uint32_t size; // set to sizeof(LocationOptions)
+ uint32_t minInterval; // in milliseconds
+ uint32_t minDistance; // in meters. if minDistance > 0, gnssSvCallback/gnssNmeaCallback/
+ // gnssMeasurementsCallback may not be called
+ GnssSuplMode mode; // Standalone/MS-Based/MS-Assisted
+ // behavior when this field is 0:
+ // if engine hub is running, this will be fused fix,
+ // if engine hub is not running, this will be SPE fix
+ LocReqEngineTypeMask locReqEngTypeMask;
+
+ inline LocationOptions() :
+ size(0), minInterval(0), minDistance(0), mode(GNSS_SUPL_MODE_STANDALONE),
+ locReqEngTypeMask((LocReqEngineTypeMask)0) {}
+};
+
+typedef enum {
+ GNSS_POWER_MODE_INVALID = 0,
+ GNSS_POWER_MODE_M1, /* Improved Accuracy Mode */
+ GNSS_POWER_MODE_M2, /* Normal Mode */
+ GNSS_POWER_MODE_M3, /* Background Mode */
+ GNSS_POWER_MODE_M4, /* Background Mode */
+ GNSS_POWER_MODE_M5 /* Background Mode */
+} GnssPowerMode;
+
+struct TrackingOptions : LocationOptions {
+ GnssPowerMode powerMode; /* Power Mode to be used for time based tracking
+ sessions */
+ uint32_t tbm; /* Time interval between measurements specified in millis.
+ Applicable to background power modes */
+
+ inline TrackingOptions() :
+ LocationOptions(), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {}
+ inline TrackingOptions(uint32_t s, GnssPowerMode m, uint32_t t) :
+ LocationOptions(), powerMode(m), tbm(t) { LocationOptions::size = s; }
+ inline TrackingOptions(const LocationOptions& options) :
+ LocationOptions(options), powerMode(GNSS_POWER_MODE_INVALID), tbm(0) {}
+ inline void setLocationOptions(const LocationOptions& options) {
+ size = sizeof(TrackingOptions);
+ minInterval = options.minInterval;
+ minDistance = options.minDistance;
+ mode = options.mode;
+ locReqEngTypeMask = options.locReqEngTypeMask;
+ }
+ inline LocationOptions getLocationOptions() {
+ LocationOptions locOption;
+ locOption.size = sizeof(locOption);
+ locOption.minDistance = minDistance;
+ locOption.minInterval = minInterval;
+ locOption.mode = mode;
+ locOption.locReqEngTypeMask = locReqEngTypeMask;
+ return locOption;
+ }
+};
+
+struct BatchingOptions : LocationOptions {
+ BatchingMode batchingMode;
+
+ inline BatchingOptions() :
+ LocationOptions(), batchingMode(BATCHING_MODE_ROUTINE) {}
+ inline BatchingOptions(uint32_t s, BatchingMode m) :
+ LocationOptions(), batchingMode(m) { LocationOptions::size = s; }
+ inline BatchingOptions(const LocationOptions& options) :
+ LocationOptions(options), batchingMode(BATCHING_MODE_ROUTINE) {}
+ inline void setLocationOptions(const LocationOptions& options) {
+ minInterval = options.minInterval;
+ minDistance = options.minDistance;
+ mode = options.mode;
+ }
+};
+
+typedef struct {
+ uint32_t size;
+ BatchingStatus batchingStatus;
+} BatchingStatusInfo;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GeofenceOption)
+ GeofenceBreachTypeMask breachTypeMask; // bitwise OR of GeofenceBreachTypeBits
+ uint32_t responsiveness; // in milliseconds
+ uint32_t dwellTime; // in seconds
+} GeofenceOption;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GeofenceInfo)
+ double latitude; // in degrees
+ double longitude; // in degrees
+ double radius; // in meters
+} GeofenceInfo;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GeofenceBreachNotification)
+ uint32_t count; // number of ids in array
+ uint32_t* ids; // array of ids that have breached
+ Location location; // location associated with breach
+ GeofenceBreachType type; // type of breach
+ uint64_t timestamp; // timestamp of breach
+} GeofenceBreachNotification;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GeofenceBreachNotification)
+ GeofenceStatusAvailable available; // GEOFENCE_STATUS_AVAILABILE_NO/_YES
+ LocationTechnologyType techType; // GNSS
+} GeofenceStatusNotification;
+
+typedef struct {
+ uint64_t gpsSvUsedIdsMask;
+ uint64_t gloSvUsedIdsMask;
+ uint64_t galSvUsedIdsMask;
+ uint64_t bdsSvUsedIdsMask;
+ uint64_t qzssSvUsedIdsMask;
+ uint64_t navicSvUsedIdsMask;
+} GnssLocationSvUsedInPosition;
+
+typedef struct {
+ /** GnssSignalType mask */
+ GnssSignalTypeMask gnssSignalType;
+ /** Specifies GNSS Constellation Type */
+ Gnss_LocSvSystemEnumType gnssConstellation;
+ /** Unique SV Identifier.
+ * For SV Range of supported constellation, please refer to
+ * the comment section of svId in GnssSv.
+ * For GLONASS: When slot-number to SV ID mapping is unknown, set as 255.
+ */
+ uint16_t gnssSvId;
+} GnssMeasUsageInfo;
+
+/** @struct
+ Body Frame parameters
+*/
+typedef struct {
+ GnssLocationPosDataMask bodyFrameDataMask; // Contains Body frame LocPosDataMask bits
+ float longAccel; // Forward Acceleration in body frame (m/s2)
+ float latAccel; // Sideward Acceleration in body frame (m/s2)
+ float vertAccel; // Vertical Acceleration in body frame (m/s2)
+ float yawRate; // Heading Rate (Radians/second)
+ float pitch; // Body pitch (Radians)
+ float longAccelUnc; // Uncertainty of Forward Acceleration in body frame
+ float latAccelUnc; // Uncertainty of Side-ward Acceleration in body frame
+ float vertAccelUnc; // Uncertainty of Vertical Acceleration in body frame
+ float yawRateUnc; // Uncertainty of Heading Rate
+ float pitchUnc; // Uncertainty of Body pitch
+} GnssLocationPositionDynamics;
+
+typedef struct {
+ GnssLocationPosDataMaskExt bodyFrameDataMask; // Contains Ext Body frame LocPosDataMask bits
+ float pitchRate; // Body pitch rate (Radians/second)
+ float pitchRateUnc; // Uncertainty of pitch rate (Radians/second)
+ float roll; // Roll of body frame. Clockwise positive. (radian
+ float rollUnc; // Uncertainty of Roll, 68% confidence level (radian)
+ float rollRate; // Roll rate of body frame. Clockwise positive. (radian/second)
+ float rollRateUnc; // Uncertainty of Roll rate, 68% confidence level (radian/second)
+ float yaw; // Yaw of body frame. Clockwise positive (radian)
+ float yawUnc; // Uncertainty of Yaw, 68% confidence level (radian)
+} GnssLocationPositionDynamicsExt;
+
+typedef struct {
+ /** Validity mask for below fields */
+ GnssSystemTimeStructTypeFlags validityMask;
+ /** Extended week number at reference tick.
+ Unit: Week.
+ Set to 65535 if week number is unknown.
+ For GPS:
+ Calculated from midnight, Jan. 6, 1980.
+ OTA decoded 10 bit GPS week is extended to map between:
+ [NV6264 to (NV6264 + 1023)].
+ NV6264: Minimum GPS week number configuration.
+ Default value of NV6264: 1738
+ For BDS:
+ Calculated from 00:00:00 on January 1, 2006 of Coordinated Universal Time (UTC).
+ For GAL:
+ Calculated from 00:00 UT on Sunday August 22, 1999 (midnight between August 21 and August 22).
+ */
+ uint16_t systemWeek;
+ /** Time in to the current week at reference tick.
+ Unit: Millisecond. Range: 0 to 604799999.
+ Check for systemClkTimeUncMs before use */
+ uint32_t systemMsec;
+ /** System clock time bias (sub-millisecond)
+ Units: Millisecond
+ Note: System time (TOW Millisecond) = systemMsec - systemClkTimeBias.
+ Check for systemClkTimeUncMs before use. */
+ float systemClkTimeBias;
+ /** Single sided maximum time bias uncertainty
+ Units: Millisecond */
+ float systemClkTimeUncMs;
+ /** FCount (free running HW timer) value. Don't use for relative time purpose
+ due to possible discontinuities.
+ Unit: Millisecond */
+ uint32_t refFCount;
+ /** Number of clock resets/discontinuities detected, affecting the local hardware counter value. */
+ uint32_t numClockResets;
+} GnssSystemTimeStructType;
+
+typedef struct {
+ /** GLONASS day number in four years. Refer to GLONASS ICD.
+ Applicable only for GLONASS and shall be ignored for other constellations.
+ If unknown shall be set to 65535 */
+ uint16_t gloDays;
+ /** Validity mask for below fields */
+ GnssGloTimeStructTypeFlags validityMask;
+ /** GLONASS time of day in Millisecond. Refer to GLONASS ICD.
+ Units: Millisecond
+ Check for gloClkTimeUncMs before use */
+ uint32_t gloMsec;
+ /** GLONASS clock time bias (sub-millisecond)
+ Units: Millisecond
+ Note: GLO time (TOD Millisecond) = gloMsec - gloClkTimeBias.
+ Check for gloClkTimeUncMs before use. */
+ float gloClkTimeBias;
+ /** Single sided maximum time bias uncertainty
+ Units: Millisecond */
+ float gloClkTimeUncMs;
+ /** FCount (free running HW timer) value. Don't use for relative time purpose
+ due to possible discontinuities.
+ Unit: Millisecond */
+ uint32_t refFCount;
+ /** Number of clock resets/discontinuities detected, affecting the local hardware counter value. */
+ uint32_t numClockResets;
+ /** GLONASS four year number from 1996. Refer to GLONASS ICD.
+ Applicable only for GLONASS and shall be ignored for other constellations.
+ If unknown shall be set to 255 */
+ uint8_t gloFourYear;
+} GnssGloTimeStructType;
+
+typedef union {
+ GnssSystemTimeStructType gpsSystemTime;
+ GnssSystemTimeStructType galSystemTime;
+ GnssSystemTimeStructType bdsSystemTime;
+ GnssSystemTimeStructType qzssSystemTime;
+ GnssGloTimeStructType gloSystemTime;
+ GnssSystemTimeStructType navicSystemTime;
+} SystemTimeStructUnion;
+ /** Time applicability of PVT report */
+typedef struct {
+ /** Specifies GNSS system time reported. Mandatory field */
+ Gnss_LocSvSystemEnumType gnssSystemTimeSrc;
+ /** Reporting of GPS system time is recommended.
+ If GPS time is unknown & other satellite system time is known,
+ it should be reported.
+ Mandatory field
+ */
+ SystemTimeStructUnion u;
+} GnssSystemTime;
+
+typedef uint32_t DrSolutionStatusMask;
+#define VEHICLE_SENSOR_SPEED_INPUT_DETECTED (1<<0)
+#define VEHICLE_SENSOR_SPEED_INPUT_USED (1<<1)
+
+typedef struct {
+ double latitude; // in degree
+ double longitude; // in degree
+ float altitude; // altitude wrt to ellipsoid
+} LLAInfo;
+
+enum loc_sess_status {
+ LOC_SESS_SUCCESS,
+ LOC_SESS_INTERMEDIATE,
+ LOC_SESS_FAILURE
+};
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssLocationInfo)
+ Location location; // basic locaiton info, latitude, longitude, and etc
+ GnssLocationInfoFlagMask flags; // bitwise OR of GnssLocationInfoBits for param validity
+ float altitudeMeanSeaLevel; // altitude wrt mean sea level
+ float pdop; // position dilusion of precision
+ float hdop; // horizontal dilusion of precision
+ float vdop; // vertical dilusion of precision
+ float gdop; // geometric dilution of precision
+ float tdop; // time dilution of precision
+ float magneticDeviation; // magnetic deviation
+ LocationReliability horReliability; // horizontal reliability
+ LocationReliability verReliability; // vertical reliability
+ float horUncEllipseSemiMajor; // horizontal elliptical accuracy semi-major axis
+ float horUncEllipseSemiMinor; // horizontal elliptical accuracy semi-minor axis
+ float horUncEllipseOrientAzimuth; // horizontal elliptical accuracy azimuth
+ float northStdDeviation; // North standard deviation Unit: Meters
+ float eastStdDeviation; // East standard deviation. Unit: Meters
+ float northVelocity; // North Velocity.Unit: Meters/sec
+ float eastVelocity; // East Velocity Unit Meters/sec
+ float upVelocity; // Up Velocity. Unit Meters/sec
+ float northVelocityStdDeviation;
+ float eastVelocityStdDeviation;
+ float upVelocityStdDeviation;
+ uint16_t numSvUsedInPosition;
+ GnssLocationSvUsedInPosition svUsedInPosition;// Gnss sv used in position data
+ GnssLocationNavSolutionMask navSolutionMask; // Nav solution mask to indicate sbas corrections
+ GnssLocationPositionDynamics bodyFrameData; // Body Frame Dynamics: 4wayAcceleration and
+ // pitch set with validity
+ GnssSystemTime gnssSystemTime; // GNSS System Time
+ uint8_t numOfMeasReceived; // Number of measurements received for use in fix.
+ GnssMeasUsageInfo measUsageInfo[GNSS_SV_MAX]; // GNSS Measurement Usage info
+ uint8_t leapSeconds; // leap second
+ float timeUncMs; // Time uncertainty in milliseconds
+ uint8_t calibrationConfidence; // Sensor calibration confidence percent,
+ // in range of [0, 100]
+ DrCalibrationStatusMask calibrationStatus; // Sensor calibration status
+ // location engine type. When the fix. when the type is set to
+ // LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated
+ // reports from all engines running on the system (e.g.:
+ // DR/SPE/PPE/VPE). To check which location engine contributes to
+ // the fused output, check for locOutputEngMask.
+ LocOutputEngineType locOutputEngType;
+ // when loc output eng type is set to fused, this field
+ // indicates the set of engines contribute to the fix.
+ PositioningEngineMask locOutputEngMask;
+ // When robust location is enabled, this field
+ // will how well the various input data considered for
+ // navigation solution conform to expectations.
+ // Range: 0 (least conforming) to 1 (most conforming)
+ float conformityIndex;
+ GnssLocationPositionDynamicsExt bodyFrameDataExt; // Additional Body Frame Dynamics
+ // VRR-based latitude/longitude/altitude
+ LLAInfo llaVRPBased;
+ // VRR-based east, north, and up velocity
+ float enuVelocityVRPBased[3];
+ DrSolutionStatusMask drSolutionStatusMask;
+ // true: altitude is assumed, false: altitude is calculated
+ bool altitudeAssumed;
+ // location session status
+ loc_sess_status sessionStatus;
+} GnssLocationInfoNotification;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssNiNotification)
+ GnssNiType type; // type of NI (Voice, SUPL, Control Plane)
+ GnssNiOptionsMask options; // bitwise OR of GnssNiOptionsBits
+ uint32_t timeout; // time (seconds) to wait for user input
+ GnssNiResponse timeoutResponse; // the response that should be sent when timeout expires
+ char requestor[GNSS_NI_REQUESTOR_MAX]; // the requestor that is making the request
+ GnssNiEncodingType requestorEncoding; // the encoding type for requestor
+ char message[GNSS_NI_MESSAGE_ID_MAX]; // the message to show user
+ GnssNiEncodingType messageEncoding; // the encoding type for message
+ char extras[GNSS_NI_MESSAGE_ID_MAX];
+} GnssNiNotification;
+
+// carrier frequency of the signal tracked
+#define GPS_L1CA_CARRIER_FREQUENCY (1575420000.0)
+#define GPS_L1C_CARRIER_FREQUENCY (1575420000.0)
+#define GPS_L2C_L_CARRIER_FREQUENCY (1227600000.0)
+#define GPS_L5_Q_CARRIER_FREQUENCY (1176450000.0)
+#define GLONASS_G1_CARRIER_FREQUENCY (1602000000.0)
+#define GLONASS_G2_CARRIER_FREQUENCY (1246000000.0)
+#define GALILEO_E1_C_CARRIER_FREQUENCY (1575420000.0)
+#define GALILEO_E5A_Q_CARRIER_FREQUENCY (1176450000.0)
+#define GALILEO_E5B_Q_CARRIER_FREQUENCY (1207140000.0)
+#define BEIDOU_B1_I_CARRIER_FREQUENCY (1561098000.0)
+#define BEIDOU_B1C_CARRIER_FREQUENCY (1575420000.0)
+#define BEIDOU_B2_I_CARRIER_FREQUENCY (1207140000.0)
+#define BEIDOU_B2A_I_CARRIER_FREQUENCY (1176450000.0)
+#define BEIDOU_B2A_Q_CARRIER_FREQUENCY (1176450000.0)
+#define QZSS_L1CA_CARRIER_FREQUENCY (1575420000.0)
+#define QZSS_L1S_CARRIER_FREQUENCY (1575420000.0)
+#define QZSS_L2C_L_CARRIER_FREQUENCY (1227600000.0)
+#define QZSS_L5_Q_CARRIER_FREQUENCY (1176450000.0)
+#define SBAS_L1_CA_CARRIER_FREQUENCY (1575420000.0)
+#define NAVIC_L5_CARRIER_FREQUENCY (1176450000.0)
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssSv)
+ // Unique SV Identifier.
+ // SV Range for supported constellation is specified as below:
+ // - For GPS: 1 to 32
+ // - For GLONASS: 65 to 96
+ // - For SBAS: 120 to 158 and 183 to 191
+ // - For QZSS: 193 to 197
+ // - For BDS: 201 to 263
+ // - For GAL: 301 to 336
+ // - For NAVIC: 401 to 414
+ uint16_t svId;
+ GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO, NAVIC)
+ float cN0Dbhz; // signal strength
+ float elevation; // elevation of SV (in degrees)
+ float azimuth; // azimuth of SV (in degrees)
+ GnssSvOptionsMask gnssSvOptionsMask; // Bitwise OR of GnssSvOptionsBits
+ float carrierFrequencyHz; // carrier frequency of the signal tracked
+ GnssSignalTypeMask gnssSignalTypeMask; // Specifies GNSS signal type
+ double basebandCarrierToNoiseDbHz; // baseband signal strength
+ uint16_t gloFrequency; // GLONASS Frequency channel number
+} GnssSv;
+
+struct GnssConfigSetAssistanceServer {
+ uint32_t size; // set to sizeof(GnssConfigSetAssistanceServer)
+ GnssAssistanceType type; // SUPL or C2K
+ const char* hostName; // null terminated string
+ uint32_t port; // port of server
+
+ inline bool equals(const GnssConfigSetAssistanceServer& config) {
+ if (config.type == type && config.port == port &&
+ ((NULL == config.hostName && NULL == hostName) ||
+ (NULL != config.hostName && NULL != hostName &&
+ 0 == strcmp(config.hostName, hostName)))) {
+ return true;
+ }
+ return false;
+ }
+};
+
+typedef struct {
+ // set to sizeof(GnssMeasurementsData)
+ uint32_t size;
+ // bitwise OR of GnssMeasurementsDataFlagsBits
+ GnssMeasurementsDataFlagsMask flags;
+ // Unique SV Identifier
+ // For SV Range of supported constellation,
+ // please refer to the comment section of svId in GnssSv.
+ int16_t svId;
+ GnssSvType svType;
+ double timeOffsetNs;
+ GnssMeasurementsStateMask stateMask; // bitwise OR of GnssMeasurementsStateBits
+ int64_t receivedSvTimeNs;
+ int64_t receivedSvTimeUncertaintyNs;
+ double carrierToNoiseDbHz;
+ double pseudorangeRateMps;
+ double pseudorangeRateUncertaintyMps;
+ GnssMeasurementsAdrStateMask adrStateMask; // bitwise OR of GnssMeasurementsAdrStateBits
+ double adrMeters;
+ double adrUncertaintyMeters;
+ float carrierFrequencyHz;
+ int64_t carrierCycles;
+ double carrierPhase;
+ double carrierPhaseUncertainty;
+ GnssMeasurementsMultipathIndicator multipathIndicator;
+ double signalToNoiseRatioDb;
+ double agcLevelDb;
+ GnssMeasurementsCodeType codeType;
+ char otherCodeTypeName[GNSS_MAX_NAME_LENGTH];
+ double basebandCarrierToNoiseDbHz;
+ GnssSignalTypeMask gnssSignalType;
+ double fullInterSignalBiasNs;
+ double fullInterSignalBiasUncertaintyNs;
+ double satelliteInterSignalBiasNs;
+ double satelliteInterSignalBiasUncertaintyNs;
+ int16_t gloFrequency;
+ uint8_t cycleSlipCount;
+} GnssMeasurementsData;
+
+typedef struct {
+ GnssSvType svType;
+ float carrierFrequencyHz;
+ GnssMeasurementsCodeType codeType;
+ char otherCodeTypeName[GNSS_MAX_NAME_LENGTH];
+} GnssMeasurementsSignalType;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssReflectingPlane)
+ double latitudeDegrees;
+ double longitudeDegrees;
+ double altitudeMeters;
+ double azimuthDegrees;
+} GnssReflectingPlane;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssSingleSatCorrection)
+ GnssSingleSatCorrectionMask flags;
+ GnssSvType svType;
+ uint16_t svId;
+ float carrierFrequencyHz;
+ float probSatIsLos;
+ float excessPathLengthMeters;
+ float excessPathLengthUncertaintyMeters;
+ GnssReflectingPlane reflectingPlane;
+} GnssSingleSatCorrection;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssMeasurementCorrections)
+ double latitudeDegrees;
+ double longitudeDegrees;
+ double altitudeMeters;
+ double horizontalPositionUncertaintyMeters;
+ double verticalPositionUncertaintyMeters;
+ uint64_t toaGpsNanosecondsOfWeek;
+ std::vector<GnssSingleSatCorrection> satCorrections;
+ bool hasEnvironmentBearing;
+ float environmentBearingDegrees;
+ float environmentBearingUncertaintyDegrees;
+} GnssMeasurementCorrections;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssMeasurementsClock)
+ GnssMeasurementsClockFlagsMask flags; // bitwise OR of GnssMeasurementsClockFlagsBits
+ int16_t leapSecond;
+ int64_t timeNs;
+ double timeUncertaintyNs;
+ int64_t fullBiasNs;
+ double biasNs;
+ double biasUncertaintyNs;
+ double driftNsps;
+ double driftUncertaintyNsps;
+ uint32_t hwClockDiscontinuityCount;
+ GnssMeasurementsSignalType referenceSignalTypeForIsb;
+ uint64_t elapsedRealTime; // in ns
+ uint64_t elapsedRealTimeUnc; // in ns
+} GnssMeasurementsClock;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssSvNotification)
+ uint32_t count; // number of SVs in the GnssSv array
+ bool gnssSignalTypeMaskValid;
+ GnssSv gnssSvs[GNSS_SV_MAX]; // information on a number of SVs
+} GnssSvNotification;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssNmeaNotification)
+ uint64_t timestamp; // timestamp
+ const char* nmea; // nmea text
+ uint32_t length; // length of the nmea text
+} GnssNmeaNotification;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssDataNotification)
+ GnssDataMask gnssDataMask[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // bitwise OR of GnssDataBits
+ double jammerInd[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Jammer Indication
+ double agc[GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES]; // Automatic gain control
+} GnssDataNotification;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssMeasurementsNotification)
+ uint32_t count; // number of items in GnssMeasurements array
+ GnssMeasurementsData measurements[GNSS_MEASUREMENTS_MAX];
+ GnssMeasurementsClock clock; // clock
+} GnssMeasurementsNotification;
+
+typedef uint32_t GnssSvId;
+
+struct GnssSvIdSource{
+ uint32_t size; // set to sizeof(GnssSvIdSource)
+ GnssSvType constellation; // constellation for the sv to blacklist
+ GnssSvId svId; // Unique SV Identifier,
+ // For SV Range of supported constellation,
+ // please refer to the comment section of svId in GnssSv.
+};
+inline bool operator ==(GnssSvIdSource const& left, GnssSvIdSource const& right) {
+ return left.size == right.size &&
+ left.constellation == right.constellation && left.svId == right.svId;
+}
+
+#define GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK ((uint64_t)0xFFFFFFFFFFFFFFFF)
+struct GnssSvIdConfig {
+ uint32_t size; // set to sizeof(GnssSvIdConfig)
+
+ // GLONASS - SV 65 maps to bit 0
+#define GNSS_SV_CONFIG_GLO_INITIAL_SV_ID 65
+ uint64_t gloBlacklistSvMask;
+
+ // BEIDOU - SV 201 maps to bit 0
+#define GNSS_SV_CONFIG_BDS_INITIAL_SV_ID 201
+ uint64_t bdsBlacklistSvMask;
+
+ // QZSS - SV 193 maps to bit 0
+#define GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID 193
+ uint64_t qzssBlacklistSvMask;
+
+ // GAL - SV 301 maps to bit 0
+#define GNSS_SV_CONFIG_GAL_INITIAL_SV_ID 301
+ uint64_t galBlacklistSvMask;
+
+ // SBAS - SV 120 to 158, maps to 0 to 38
+ // SV 183 to 191, maps to 39 to 47
+#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120
+#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
+#define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183
+ uint64_t sbasBlacklistSvMask;
+
+ //Navic - SV 401 maps to bit 0
+#define GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID 401
+ uint64_t navicBlacklistSvMask;
+
+ inline bool equals(const GnssSvIdConfig& inConfig) {
+ if ((inConfig.size == size) &&
+ (inConfig.gloBlacklistSvMask == gloBlacklistSvMask) &&
+ (inConfig.bdsBlacklistSvMask == bdsBlacklistSvMask) &&
+ (inConfig.qzssBlacklistSvMask == qzssBlacklistSvMask) &&
+ (inConfig.galBlacklistSvMask == galBlacklistSvMask) &&
+ (inConfig.sbasBlacklistSvMask == sbasBlacklistSvMask) &&
+ (inConfig.navicBlacklistSvMask == navicBlacklistSvMask)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+};
+
+// Specify the valid mask for robust location configure
+// defined in GnssConfigRobustLocation.
+enum GnssConfigRobustLocationValidMask {
+ // GnssConfigRobustLocation has valid enabled field.
+ GNSS_CONFIG_ROBUST_LOCATION_ENABLED_VALID_BIT = (1<<0),
+ // GnssConfigRobustLocation has valid enabledForE911 field.
+ GNSS_CONFIG_ROBUST_LOCATION_ENABLED_FOR_E911_VALID_BIT = (1<<1),
+ // GnssConfigRobustLocation has valid version field.
+ GNSS_CONFIG_ROBUST_LOCATION_VERSION_VALID_BIT = (1<<2),
+};
+
+struct GnssConfigRobustLocationVersion {
+ // Major version number
+ uint8_t major;
+ // Minor version number
+ uint16_t minor;
+ inline bool equals(const GnssConfigRobustLocationVersion& version) const {
+ return (version.major == major && version.minor == minor);
+ }
+};
+
+// specify the robust location configuration used by modem GNSS engine
+struct GnssConfigRobustLocation {
+ GnssConfigRobustLocationValidMask validMask;
+ bool enabled;
+ bool enabledForE911;
+ GnssConfigRobustLocationVersion version;
+
+ inline bool equals(const GnssConfigRobustLocation& config) const {
+ if (config.validMask == validMask &&
+ config.enabled == enabled &&
+ config.enabledForE911 == enabledForE911 &&
+ config.version.equals(version)) {
+ return true;
+ }
+ return false;
+ }
+};
+
+/* Mask indicating enabled or disabled constellations and
+ secondary frequency.*/
+typedef uint64_t GnssSvTypesMask;
+typedef enum {
+ GNSS_SV_TYPES_MASK_GLO_BIT = (1<<0),
+ GNSS_SV_TYPES_MASK_BDS_BIT = (1<<1),
+ GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2),
+ GNSS_SV_TYPES_MASK_GAL_BIT = (1<<3),
+ GNSS_SV_TYPES_MASK_NAVIC_BIT = (1<<4),
+ GNSS_SV_TYPES_MASK_GPS_BIT = (1<<5),
+} GnssSvTypesMaskBits;
+#define GNSS_SV_TYPES_MASK_ALL \
+ (GNSS_SV_TYPES_MASK_GPS_BIT|GNSS_SV_TYPES_MASK_GLO_BIT|GNSS_SV_TYPES_MASK_BDS_BIT|\
+ GNSS_SV_TYPES_MASK_QZSS_BIT|GNSS_SV_TYPES_MASK_GAL_BIT|GNSS_SV_TYPES_MASK_NAVIC_BIT)
+
+/* This SV Type config is injected directly to GNSS Adapter
+ * bypassing Location API */
+struct GnssSvTypeConfig{
+ uint32_t size; // set to sizeof(GnssSvTypeConfig)
+ // Enabled Constellations
+ GnssSvTypesMask enabledSvTypesMask;
+ // Disabled Constellations
+ GnssSvTypesMask blacklistedSvTypesMask;
+
+ inline bool equals (const GnssSvTypeConfig& inConfig) const {
+ return ((inConfig.size == size) &&
+ (inConfig.enabledSvTypesMask == enabledSvTypesMask) &&
+ (inConfig.blacklistedSvTypesMask == blacklistedSvTypesMask));
+ }
+};
+
+struct GnssConfig{
+ uint32_t size; // set to sizeof(GnssConfig)
+ GnssConfigFlagsMask flags; // bitwise OR of GnssConfigFlagsBits to mark which params are valid
+ GnssConfigGpsLock gpsLock;
+ GnssConfigSuplVersion suplVersion;
+ GnssConfigSetAssistanceServer assistanceServer;
+ GnssConfigLppProfileMask lppProfileMask;
+ GnssConfigLppeControlPlaneMask lppeControlPlaneMask;
+ GnssConfigLppeUserPlaneMask lppeUserPlaneMask;
+ GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask;
+ GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl;
+ GnssConfigSuplEmergencyServices suplEmergencyServices;
+ GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits
+ std::vector<GnssSvIdSource> blacklistedSvIds;
+ uint32_t emergencyExtensionSeconds;
+ GnssConfigRobustLocation robustLocationConfig;
+ uint16_t minGpsWeek;
+ uint8_t minSvElevation;
+ GnssSvTypeConfig secondaryBandConfig;
+
+ inline bool equals(const GnssConfig& config) {
+ if (flags == config.flags &&
+ gpsLock == config.gpsLock &&
+ suplVersion == config.suplVersion &&
+ assistanceServer.equals(config.assistanceServer) &&
+ lppProfileMask == config.lppProfileMask &&
+ lppeControlPlaneMask == config.lppeControlPlaneMask &&
+ lppeUserPlaneMask == config.lppeUserPlaneMask &&
+ aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask &&
+ emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl &&
+ suplEmergencyServices == config.suplEmergencyServices &&
+ suplModeMask == config.suplModeMask &&
+ blacklistedSvIds == config.blacklistedSvIds &&
+ emergencyExtensionSeconds == config.emergencyExtensionSeconds &&
+ robustLocationConfig.equals(config.robustLocationConfig) &&
+ minGpsWeek == config.minGpsWeek &&
+ minSvElevation == config.minSvElevation &&
+ secondaryBandConfig.equals(config.secondaryBandConfig)) {
+ return true;
+ }
+ return false;
+ }
+};
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ bool mValid;
+ Location mLocation;
+ double verticalAccuracyMeters;
+ double speedAccuracyMetersPerSecond;
+ double bearingAccuracyDegrees;
+ timespec mUtcReported;
+} GnssDebugLocation;
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ bool mValid;
+ int64_t timeEstimate;
+ float timeUncertaintyNs;
+ float frequencyUncertaintyNsPerSec;
+} GnssDebugTime;
+
+typedef struct {
+ // set to sizeof
+ uint32_t size;
+ // Unique SV Identifier
+ // For SV Range of supported constellation,
+ // please refer to the comment section of svId in GnssSv.
+ uint32_t svid;
+ GnssSvType constellation;
+ GnssEphemerisType mEphemerisType;
+ GnssEphemerisSource mEphemerisSource;
+ GnssEphemerisHealth mEphemerisHealth;
+ float ephemerisAgeSeconds;
+ bool serverPredictionIsAvailable;
+ float serverPredictionAgeSeconds;
+} GnssDebugSatelliteInfo;
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ GnssDebugLocation mLocation;
+ GnssDebugTime mTime;
+ std::vector<GnssDebugSatelliteInfo> mSatelliteInfo;
+} GnssDebugReport;
+
+typedef uint32_t LeapSecondSysInfoMask;
+typedef enum {
+ // current leap second info is available. This info will only
+ // be available if the leap second change info is not available.
+ //
+ // If leap second change info is avaiable, to figure out
+ // the current leap second info, compare current gps time with
+ // the gps timestamp of leap second change to know whether to choose
+ // leapSecondBefore or leapSecondAfter as current leap second.
+ LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT = (1ULL << 0),
+ // the last known leap change event is available.
+ // The info can be available on two scenario:
+ // 1: this leap second change event has been scheduled and yet to happen
+ // 2: this leap second change event has already happened and next
+ // leap second change event has not yet been scheduled.
+ LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT = (1ULL << 1),
+} LeapSecondSysInfoDataBits;
+
+struct LeapSecondChangeInfo {
+ // GPS timestamp that corrresponds to the last known
+ // leap second change event.
+ //
+ // The info can be available on two scenario:
+ // 1: this leap second change event has been scheduled and yet to happen
+ // 2: this leap second change event has already happened and next
+ // leap second change event has not yet been scheduled.
+ GnssSystemTimeStructType gpsTimestampLsChange;
+ // Number of leap seconds prior to the leap second change event
+ // that corresponds to the timestamp at gpsTimestampLsChange.
+ uint8_t leapSecondsBeforeChange;
+ // Number of leap seconds after the leap second change event
+ // that corresponds to the timestamp at gpsTimestampLsChange.
+ uint8_t leapSecondsAfterChange;
+};
+
+struct LeapSecondSystemInfo {
+ LeapSecondSysInfoMask leapSecondInfoMask;
+ uint8_t leapSecondCurrent;
+ LeapSecondChangeInfo leapSecondChangeInfo;
+};
+
+typedef uint32_t LocationSystemInfoMask;
+typedef enum {
+ // contains current leap second or leap second change info
+ LOCATION_SYS_INFO_LEAP_SECOND = (1ULL << 0),
+} LocationSystemInfoDataBits;
+
+struct LocationSystemInfo {
+ LocationSystemInfoMask systemInfoMask;
+ LeapSecondSystemInfo leapSecondSysInfo;
+};
+
+// Specify the set of terrestrial technologies
+enum TerrestrialTechMask {
+ TERRESTRIAL_TECH_GTP_WWAN = 1 << 0,
+};
+
+// Specify parameters related to lever arm
+struct LeverArmParams {
+ // Offset along the vehicle forward axis
+ float forwardOffsetMeters;
+ // Offset along the vehicle starboard axis
+ float sidewaysOffsetMeters;
+ // Offset along the vehicle up axis
+ float upOffsetMeters;
+};
+
+typedef uint32_t LeverArmTypeMask;
+
+enum LeverArmTypeBits {
+ // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t
+ // the origin (at the GPS Antenna)
+ LEVER_ARM_TYPE_GNSS_TO_VRP_BIT = (1<<0),
+ // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU
+ // e.g.: inertial measurement unit for DR (dead reckoning
+ // engine)
+ LEVER_ARM_TYPE_DR_IMU_TO_GNSS_BIT = (1<<1),
+ // Lever arm regarding GNSS Antenna w.r.t the origin at the
+ // IMU (inertial measurement unit) for VEPP (vision enhanced
+ // precise positioning engine)
+ LEVER_ARM_TYPE_VEPP_IMU_TO_GNSS_BIT = (1<<2)
+};
+
+struct LeverArmConfigInfo {
+ // Valid mask for the types of lever arm parameters provided
+ LeverArmTypeMask leverArmValidMask;
+ // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t the origin
+ // (at the GPS Antenna)
+ LeverArmParams gnssToVRP;
+ // Lever arm parameters regarding GNSS Antenna w.r.t the origin at the IMU
+ // (inertial measurement unit) for DR (dead reckoning engine)
+ LeverArmParams drImuToGnss;
+ // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU
+ // (inertial measurement unit) for VEPP (vision enhanced precise position engine)
+ LeverArmParams veppImuToGnss;
+};
+
+// Specify vehicle body-to-Sensor mount parameters to be used
+// by dead reckoning positioning engine.
+struct BodyToSensorMountParams {
+ // The misalignment of the sensor board along the
+ // horizontal plane of the vehicle chassis measured looking
+ // from the vehicle to forward direction. In unit of degree.
+ float rollOffset;
+ // The misalignment along the horizontal plane of the vehicle
+ // chassis measured looking from the vehicle to the right
+ // side. Positive pitch indicates vehicle is inclined such
+ // that forward wheels are at higher elevation than rear
+ // wheels. In unit of degree.
+ float yawOffset;
+ // The angle between the vehicle forward direction and the
+ // sensor axis as seen from the top of the vehicle, and
+ // measured in counterclockwise direction. In unit of degree.
+ float pitchOffset;
+ // Single uncertainty number that may be the largest of the
+ // roll, pitch and yaw offset uncertainties.
+ float offsetUnc;
+};
+
+typedef uint64_t DeadReckoningEngineConfigValidMask;
+// Specify the valid mask for the configuration paramters of
+// dead reckoning position engine.
+enum DeadReckoningEngineConfigValidBit {
+ // DeadReckoningEngineConfig has valid
+ // DeadReckoningEngineConfig::DeadReckoningEngineConfig.
+ BODY_TO_SENSOR_MOUNT_PARAMS_BIT = (1<<0),
+ // DeadReckoningEngineConfig has valid
+ // DeadReckoningEngineConfig::vehicleSpeedScaleFactor.
+ VEHICLE_SPEED_SCALE_FACTOR_BIT = (1<<1),
+ // DeadReckoningEngineConfig has valid
+ // DeadReckoningEngineConfig::vehicleSpeedScaleFactorUnc.
+ VEHICLE_SPEED_SCALE_FACTOR_UNC_BIT = (1<<2),
+ // DeadReckoningEngineConfig has valid
+ // DeadReckoningEngineConfig::gyroScaleFactor.
+ GYRO_SCALE_FACTOR_BIT = (1<<3),
+ // DeadReckoningEngineConfig has valid
+ // DeadReckoningEngineConfig::gyroScaleFactorUnc.
+ GYRO_SCALE_FACTOR_UNC_BIT = (1<<4),
+};
+
+// Specify the configuration parameters for the dead reckoning
+// position engine
+struct DeadReckoningEngineConfig{
+ // Specify the valid fields in the config.
+ DeadReckoningEngineConfigValidMask validMask;
+ // Body to sensor mount parameters for use by dead reckoning
+ // positioning engine
+ BodyToSensorMountParams bodyToSensorMountParams;
+
+ // Vehicle Speed Scale Factor configuration input for the dead
+ // reckoning positioning engine. The multiplicative scale
+ // factor is applied to received Vehicle Speed value (in m/s)
+ // to obtain the true Vehicle Speed.
+ //
+ // Range is [0.9 to 1.1].
+ //
+ // Note: The scale factor is specific to a given vehicle
+ // make & model.
+ float vehicleSpeedScaleFactor;
+ // Vehicle Speed Scale Factor Uncertainty (68% confidence)
+ // configuration input for the dead reckoning positioning
+ // engine.
+ //
+ // Range is [0.0 to 0.1].
+ //
+ // Note: The scale factor unc is specific to a given vehicle
+ // make & model.
+ float vehicleSpeedScaleFactorUnc;
+
+ // Gyroscope Scale Factor configuration input for the dead
+ // reckoning positioning engine. The multiplicative scale
+ // factor is applied to received gyroscope value to obtain the
+ // true value.
+ //
+ // Range is [0.9 to 1.1].
+ //
+ // Note: The scale factor is specific to the Gyroscope sensor
+ // and typically derived from either sensor data-sheet or
+ // from actual calibration.
+ float gyroScaleFactor;
+
+ // Gyroscope Scale Factor uncertainty (68% confidence)
+ // configuration input for the dead reckoning positioning
+ // engine.
+ //
+ // Range is [0.0 to 0.1].
+ // engine.
+ //
+ // Note: The scale factor unc is specific to the make & model
+ // of Gyroscope sensor and typically derived from either
+ // sensor data-sheet or from actual calibration.
+ float gyroScaleFactorUnc;
+};
+
+/* Provides the capabilities of the system
+ capabilities callback is called once soon after createInstance is called */
+typedef std::function<void(
+ LocationCapabilitiesMask capabilitiesMask // bitwise OR of LocationCapabilitiesBits
+)> capabilitiesCallback;
+
+/* Used by tracking, batching, and miscellanous APIs
+ responseCallback is called for every Tracking, Batching API, and Miscellanous API */
+typedef std::function<void(
+ LocationError err, // if not SUCCESS, then id is not valid
+ uint32_t id // id to be associated to the request
+)> responseCallback;
+
+/* Used by APIs that gets more than one LocationError in it's response
+ collectiveResponseCallback is called for every geofence API call.
+ ids array and LocationError array are only valid until collectiveResponseCallback returns. */
+typedef std::function<void(
+ uint32_t count, // number of locations in arrays
+ LocationError* errs, // array of LocationError associated to the request
+ uint32_t* ids // array of ids to be associated to the request
+)> collectiveResponseCallback;
+
+/* Used for startTracking API, optional can be NULL
+ trackingCallback is called when delivering a location in a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ Location location
+)> trackingCallback;
+
+/* Used for startBatching API, optional can be NULL
+ batchingCallback is called when delivering locations in a batching session.
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ uint32_t count, // number of locations in array
+ Location* location, // array of locations
+ BatchingOptions batchingOptions // Batching options
+)> batchingCallback;
+
+typedef std::function<void(
+ BatchingStatusInfo batchingStatus, // batch status
+ std::list<uint32_t> & listOfCompletedTrips
+)> batchingStatusCallback;
+
+/* Gives GNSS Location information, optional can be NULL
+ gnssLocationInfoCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ GnssLocationInfoNotification gnssLocationInfoNotification
+)> gnssLocationInfoCallback;
+
+/* Gives default combined location information from all engines and
+ location information individually from selected engines.
+ This callback is only used when there are multiple engines
+ running in the system.
+
+ optional can be NULL
+
+ engineLocationsInfoCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ uint32_t count,
+ GnssLocationInfoNotification* engineLocationInfoNotification
+)> engineLocationsInfoCallback;
+
+/* Used for addGeofences API, optional can be NULL
+ geofenceBreachCallback is called when any number of geofences have a state change */
+typedef std::function<void(
+ GeofenceBreachNotification geofenceBreachNotification
+)> geofenceBreachCallback;
+
+/* Used for addGeofences API, optional can be NULL
+ geofenceStatusCallback is called when any number of geofences have a status change */
+typedef std::function<void(
+ GeofenceStatusNotification geofenceStatusNotification
+)> geofenceStatusCallback;
+
+/* Network Initiated request, optional can be NULL
+ This callback should be responded to by calling gnssNiResponse */
+typedef std::function<void(
+ uint32_t id, // id that should be used to respond by calling gnssNiResponse
+ GnssNiNotification gnssNiNotification
+)> gnssNiCallback;
+
+/* Gives GNSS SV information, optional can be NULL
+ gnssSvCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ GnssSvNotification gnssSvNotification
+)> gnssSvCallback;
+
+/* Gives GNSS NMEA data, optional can be NULL
+ gnssNmeaCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ GnssNmeaNotification gnssNmeaNotification
+)> gnssNmeaCallback;
+
+/* Gives GNSS data, optional can be NULL
+ gnssDataCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ GnssDataNotification gnssDataNotification
+)> gnssDataCallback;
+
+/* Gives GNSS Measurements information, optional can be NULL
+ gnssMeasurementsCallback is called only during a tracking session
+ broadcasted to all clients, no matter if a session has started by client */
+typedef std::function<void(
+ GnssMeasurementsNotification gnssMeasurementsNotification
+)> gnssMeasurementsCallback;
+
+/* Provides the current GNSS configuration to the client */
+typedef std::function<void(
+ uint32_t session_id,
+ const GnssConfig& config
+)> gnssConfigCallback;
+
+/* LocationSystemInfoCb is for receiving rare occuring location
+ system information update. optional, can be NULL.
+*/
+typedef std::function<void(
+ LocationSystemInfo locationSystemInfo
+)> locationSystemInfoCallback;
+
+typedef std::function<void(
+)> locationApiDestroyCompleteCallback;
+
+typedef uint16_t LocationAdapterTypeMask;
+typedef enum {
+ LOCATION_ADAPTER_GNSS_TYPE_BIT = (1<<0), // adapter type is GNSS
+ LOCATION_ADAPTER_BATCHING_TYPE_BIT = (1<<1), // adapter type is BATCHING
+ LOCATION_ADAPTER_GEOFENCE_TYPE_BIT = (1<<2) // adapter type is geo fence
+} LocationAdapterTypeBits;
+
+typedef struct {
+ uint32_t size; // set to sizeof(LocationCallbacks)
+ capabilitiesCallback capabilitiesCb; // mandatory
+ responseCallback responseCb; // mandatory
+ collectiveResponseCallback collectiveResponseCb; // mandatory
+ trackingCallback trackingCb; // optional
+ batchingCallback batchingCb; // optional
+ geofenceBreachCallback geofenceBreachCb; // optional
+ geofenceStatusCallback geofenceStatusCb; // optional
+ gnssLocationInfoCallback gnssLocationInfoCb; // optional
+ gnssNiCallback gnssNiCb; // optional
+ gnssSvCallback gnssSvCb; // optional
+ gnssNmeaCallback gnssNmeaCb; // optional
+ gnssDataCallback gnssDataCb; // optional
+ gnssMeasurementsCallback gnssMeasurementsCb; // optional
+ batchingStatusCallback batchingStatusCb; // optional
+ locationSystemInfoCallback locationSystemInfoCb; // optional
+ engineLocationsInfoCallback engineLocationsInfoCb; // optional
+} LocationCallbacks;
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ double x;
+ double xUncertainty;
+ double y;
+ double yUncertainty;
+ double z;
+ double zUncertainty;
+} GnssCoordinate;
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ double carrierFrequencyMHz;
+ GnssCoordinate phaseCenterOffsetCoordinateMillimeters;
+ std::vector<std::vector<double>> phaseCenterVariationCorrectionMillimeters;
+ std::vector<std::vector<double>> phaseCenterVariationCorrectionUncertaintyMillimeters;
+ std::vector<std::vector<double>> signalGainCorrectionDbi;
+ std::vector<std::vector<double>> signalGainCorrectionUncertaintyDbi;
+} GnssAntennaInformation;
+
+typedef struct {
+ uint32_t size; // set to sizeof
+ bool requiresNmeaLocation;
+ std::string hostNameOrIp; // null terminated string
+ std::string mountPoint; // null terminated string
+ std::string username; // null terminated string
+ std::string password; // null terminated string
+ uint32_t port;
+ bool useSSL;
+} GnssNtripConnectionParams;
+
+typedef struct {
+ uint64_t meQtimer1;
+ uint64_t meQtimer2;
+ uint64_t meQtimer3;
+ uint64_t peQtimer1;
+ uint64_t peQtimer2;
+ uint64_t peQtimer3;
+ uint64_t smQtimer1;
+ uint64_t smQtimer2;
+ uint64_t smQtimer3;
+ uint64_t locMwQtimer;
+ uint64_t hlosQtimer1;
+ uint64_t hlosQtimer2;
+ uint64_t hlosQtimer3;
+ uint64_t hlosQtimer4;
+ uint64_t hlosQtimer5;
+} GnssLatencyInfo;
+
+#endif /* LOCATIONDATATYPES_H */
diff --git a/gps/location/Makefile.am b/gps/location/Makefile.am
new file mode 100644
index 0000000..6a5a750
--- /dev/null
+++ b/gps/location/Makefile.am
@@ -0,0 +1,44 @@
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS = \
+ -I./ \
+ -I../utils \
+ $(LOCPLA_CFLAGS) \
+ $(GPSUTILS_CFLAGS) \
+ -std=c++11
+
+liblocation_api_la_SOURCES = \
+ LocationAPI.cpp \
+ LocationAPIClientBase.cpp
+
+if USE_EXTERNAL_AP
+AM_CFLAGS += -DFEATURE_EXTERNAL_AP
+endif
+
+if USE_GLIB
+liblocation_api_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
+liblocation_api_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
+liblocation_api_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
+else
+liblocation_api_la_CFLAGS = $(AM_CFLAGS)
+liblocation_api_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
+liblocation_api_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+liblocation_api_la_LIBADD = -lstdc++ -ldl $(GPSUTILS_LIBS)
+
+library_include_HEADERS = \
+ LocationAPI.h \
+ LocationAPIClientBase.h \
+ location_interface.h \
+ LocationDataTypes.h \
+ ILocationAPI.h
+
+#Create and Install libraries
+lib_LTLIBRARIES = liblocation_api.la
+
+library_includedir = $(pkgincludedir)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = location-api.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/gps/location/configure.ac b/gps/location/configure.ac
new file mode 100644
index 0000000..f8376f5
--- /dev/null
+++ b/gps/location/configure.ac
@@ -0,0 +1,95 @@
+# configure.ac -- Autoconf script for gps location-api-iface
+#
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the gps location-api-iface package version 1.0.0
+AC_INIT([location-api-iface],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# Verifies the --srcdir is correct by checking for the path
+AC_CONFIG_SRCDIR([location-api.pc.in])
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
+AC_SUBST([GPSUTILS_CFLAGS])
+AC_SUBST([GPSUTILS_LIBS])
+
+AC_ARG_WITH([core_includes],
+ AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+ [Specify the location of the core headers]),
+ [core_incdir=$withval],
+ with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [Specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x${with_locpla_includes}" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_SUBST([CPPFLAGS])
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+# External AP
+AC_ARG_WITH([external_ap],
+ AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
+ [Using External Application Processor]),
+ [],
+ with_external_ap=no)
+
+if test "x$with_external_ap" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
+fi
+
+AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ location-api.pc \
+ ])
+
+AC_OUTPUT
diff --git a/gps/location/location-api.pc.in b/gps/location/location-api.pc.in
new file mode 100644
index 0000000..c7b146a
--- /dev/null
+++ b/gps/location/location-api.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: location-api
+Description: Location API
+Version: @VERSION
+Libs: -L${libdir} -llocation_api
+Cflags: -I${includedir}/location-api
diff --git a/gps/location/location_interface.h b/gps/location/location_interface.h
new file mode 100644
index 0000000..69d4f0c
--- /dev/null
+++ b/gps/location/location_interface.h
@@ -0,0 +1,144 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LOCATION_INTERFACE_H
+#define LOCATION_INTERFACE_H
+
+#include <LocationAPI.h>
+#include <gps_extended_c.h>
+#include <functional>
+
+/* Used for callback to deliver GNSS energy consumed */
+/** @fn
+ @brief Used by query API that retrieves energy consumed by
+ modem GNSS engine.
+
+ @param gnssEnergyConsumedFromFirstBoot:
+ Energy consumed by the GNSS engine since the first bootup
+ in units of 0.1 milli watt seconds.
+ A value of 0xffffffffffffffff indicates an invalid reading.
+*/
+typedef std::function<void(
+ uint64_t gnssEnergyConsumedFromFirstBoot
+)> GnssEnergyConsumedCallback;
+
+typedef void (*removeClientCompleteCallback)(LocationAPI* client);
+
+struct GnssInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+ void (*requestCapabilities)(LocationAPI* client);
+ uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
+ void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
+ void (*stopTracking)(LocationAPI* client, uint32_t id);
+ void (*gnssNiResponse)(LocationAPI* client, uint32_t id, GnssNiResponse response);
+ void (*setControlCallbacks)(LocationControlCallbacks& controlCallbacks);
+ uint32_t (*enable)(LocationTechnologyType techType);
+ void (*disable)(uint32_t id);
+ uint32_t* (*gnssUpdateConfig)(const GnssConfig& config);
+ uint32_t* (*gnssGetConfig)(GnssConfigFlagsMask config);
+ void (*gnssUpdateSvTypeConfig)(GnssSvTypeConfig& config);
+ void (*gnssGetSvTypeConfig)(GnssSvTypeConfigCallback& callback);
+ void (*gnssResetSvTypeConfig)();
+ uint32_t (*gnssDeleteAidingData)(GnssAidingData& data);
+ void (*gnssUpdateXtraThrottle)(const bool enabled);
+ void (*injectLocation)(double latitude, double longitude, float accuracy);
+ void (*injectTime)(int64_t time, int64_t timeReference, int32_t uncertainty);
+ void (*agpsInit)(const AgpsCbInfo& cbInfo);
+ void (*agpsDataConnOpen)(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType);
+ void (*agpsDataConnClosed)(AGpsExtType agpsType);
+ void (*agpsDataConnFailed)(AGpsExtType agpsType);
+ void (*getDebugReport)(GnssDebugReport& report);
+ void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming,
+ NetworkHandle networkHandle, std::string& apn);
+ void (*odcpiInit)(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
+ void (*odcpiInject)(const Location& location);
+ void (*blockCPI)(double latitude, double longitude, float accuracy,
+ int blockDurationMsec, double latLonDiffThreshold);
+ void (*getGnssEnergyConsumed)(GnssEnergyConsumedCallback energyConsumedCb);
+ void (*enableNfwLocationAccess)(bool enable);
+ void (*nfwInit)(const NfwCbInfo& cbInfo);
+ void (*getPowerStateChanges)(std::function<void(bool)> powerStateCb);
+ void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo);
+ void (*updateBatteryStatus)(bool charging);
+ void (*updateSystemPowerState)(PowerStateType systemPowerState);
+ uint32_t (*setConstrainedTunc) (bool enable, float tuncConstraint, uint32_t energyBudget);
+ uint32_t (*setPositionAssistedClockEstimator) (bool enable);
+ uint32_t (*gnssUpdateSvConfig)(const GnssSvTypeConfig& constellationEnablementConfig,
+ const GnssSvIdConfig& blacklistSvConfig);
+ uint32_t (*configLeverArm)(const LeverArmConfigInfo& configInfo);
+ bool (*measCorrInit)(const measCorrSetCapabilitiesCb setCapabilitiesCb);
+ bool (*measCorrSetCorrections)(const GnssMeasurementCorrections gnssMeasCorr);
+ void (*measCorrClose)();
+ uint32_t (*antennaInfoInit)(const antennaInfoCb antennaInfoCallback);
+ void (*antennaInfoClose) ();
+ uint32_t (*configRobustLocation)(bool enable, bool enableForE911);
+ uint32_t (*configMinGpsWeek)(uint16_t minGpsWeek);
+ uint32_t (*configDeadReckoningEngineParams)(const DeadReckoningEngineConfig& dreConfig);
+ void (*updateNTRIPGGAConsent)(bool consentAccepted);
+ void (*enablePPENtripStream)(const GnssNtripConnectionParams& params, bool enableRTKEngine);
+ void (*disablePPENtripStream)();
+ uint32_t (*gnssUpdateSecondaryBandConfig)(const GnssSvTypeConfig& secondaryBandConfig);
+ uint32_t (*gnssGetSecondaryBandConfig)();
+ void (*resetNetworkInfo)();
+ uint32_t (*configEngineRunState)(PositioningEngineMask engType,
+ LocEngineRunState engState);
+};
+
+struct BatchingInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+ void (*requestCapabilities)(LocationAPI* client);
+ uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&);
+ void (*stopBatching)(LocationAPI* client, uint32_t id);
+ void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&);
+ void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count);
+};
+
+struct GeofenceInterface {
+ size_t size;
+ void (*initialize)(void);
+ void (*deinitialize)(void);
+ void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
+ void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
+ void (*requestCapabilities)(LocationAPI* client);
+ uint32_t* (*addGeofences)(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*);
+ void (*removeGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
+ void (*modifyGeofences)(LocationAPI* client, size_t count, uint32_t* ids,
+ GeofenceOption* options);
+ void (*pauseGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
+ void (*resumeGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
+};
+
+#endif /* LOCATION_INTERFACE_H */
diff --git a/gps/pla/Android.bp b/gps/pla/Android.bp
new file mode 100644
index 0000000..5f240eb
--- /dev/null
+++ b/gps/pla/Android.bp
@@ -0,0 +1,7 @@
+
+cc_library_headers {
+
+ name: "libloc_pla_headers",
+ export_include_dirs: ["android"],
+ vendor: true,
+}
diff --git a/gps/pla/android/loc_pla.h b/gps/pla/android/loc_pla.h
new file mode 100644
index 0000000..34cb591
--- /dev/null
+++ b/gps/pla/android/loc_pla.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LOC_PLA__
+#define __LOC_PLA__
+
+#ifdef __cplusplus
+#include <utils/SystemClock.h>
+#define uptimeMillis() android::uptimeMillis()
+#define elapsedRealtime() android::elapsedRealtime()
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cutils/properties.h>
+#include <cutils/threads.h>
+#include <cutils/sched_policy.h>
+#include <cutils/android_filesystem_config.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define UID_GPS (AID_GPS)
+#define GID_GPS (AID_GPS)
+#define UID_LOCCLIENT (4021)
+#define GID_LOCCLIENT (4021)
+
+#define LOC_PATH_GPS_CONF_STR "/vendor/etc/gps.conf"
+#define LOC_PATH_IZAT_CONF_STR "/vendor/etc/izat.conf"
+#define LOC_PATH_FLP_CONF_STR "/vendor/etc/flp.conf"
+#define LOC_PATH_LOWI_CONF_STR "/vendor/etc/lowi.conf"
+#define LOC_PATH_SAP_CONF_STR "/vendor/etc/sap.conf"
+#define LOC_PATH_APDR_CONF_STR "/vendor/etc/apdr.conf"
+#define LOC_PATH_XTWIFI_CONF_STR "/vendor/etc/xtwifi.conf"
+#define LOC_PATH_QUIPC_CONF_STR "/vendor/etc/quipc.conf"
+#define LOC_PATH_ANT_CORR_STR "/vendor/etc/gnss_antenna_info.conf"
+#define LOC_PATH_SLIM_CONF_STR "/vendor/etc/slim.conf"
+#define LOC_PATH_VPE_CONF_STR "/vendor/etc/vpeglue.conf"
+
+/*!
+ * @brief Function for memory block copy
+ *
+ * @param[out] p_Dest Destination buffer.
+ * @param[in] q_DestSize Destination buffer size.
+ * @param[in] p_Src Source buffer.
+ * @param[in] q_SrcSize Source buffer size.
+ *
+ * @return Number of bytes copied.
+ */
+static inline size_t memscpy (void *p_Dest, size_t q_DestSize, const void *p_Src, size_t q_SrcSize)
+{
+ size_t res = (q_DestSize < q_SrcSize) ? q_DestSize : q_SrcSize;
+ if (p_Dest && p_Src && q_DestSize > 0 && q_SrcSize > 0) {
+ memcpy(p_Dest, p_Src, res);
+ } else {
+ res = 0;
+ }
+ return res;
+}
+
+/*API for boot kpi marker prints */
+inline int loc_boot_kpi_marker(const char * pFmt, ...)
+{
+ return -1;
+}
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus */
+
+#endif /* __LOC_PLA__ */
diff --git a/gps/pla/oe/loc_pla.h b/gps/pla/oe/loc_pla.h
new file mode 100644
index 0000000..268b6bf
--- /dev/null
+++ b/gps/pla/oe/loc_pla.h
@@ -0,0 +1,175 @@
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LOC_PLA__
+#define __LOC_PLA__
+
+#ifdef __cplusplus
+#ifndef FEATURE_EXTERNAL_AP
+#include <utils/SystemClock.h>
+#endif /* FEATURE_EXTERNAL_AP */
+#include <inttypes.h>
+#include <sys/time.h>
+#include <time.h>
+
+#if defined(__GNUC__) && defined(__GNUC_PREREQ)
+#if __GNUC_PREREQ(6,0)
+ #pragma message "GNU C version is above 6"
+#else
+ #pragma message "GNU C version is less than 6"
+ #define NO_UNORDERED_SET_OR_MAP
+#endif
+#endif
+
+// use set/map instead of unordered_set/unordered_map for
+// older GCC versions
+#ifdef NO_UNORDERED_SET_OR_MAP
+#define unordered_set set
+#define unordered_map map
+#endif
+
+inline int64_t sysTimeMillis(int clock)
+{
+ struct timespec ts;
+ int64_t time_ms = 0;
+ clock_gettime(clock, &ts);
+ time_ms += (ts.tv_sec * 1000000000LL);
+ time_ms += ts.tv_nsec + 500000LL;
+ return time_ms / 1000000LL;
+}
+
+inline int64_t uptimeMillis() {
+ return sysTimeMillis(CLOCK_MONOTONIC);
+}
+inline int64_t elapsedRealtime() {
+ return sysTimeMillis(CLOCK_BOOTTIME);
+}
+
+extern "C" {
+#endif
+
+#ifndef FEATURE_EXTERNAL_AP
+#include <cutils/properties.h>
+#include <cutils/threads.h>
+#include <cutils/sched_policy.h>
+#else
+#define set_sched_policy(a, b)
+#endif /* FEATURE_EXTERNAL_AP */
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#define MAX_COMMAND_STR_LEN (255)
+#define BOOT_KPI_FILE "/sys/kernel/debug/bootkpi/kpi_values"
+#ifndef OFF_TARGET
+#include <glib.h>
+#define strlcat g_strlcat
+#define strlcpy g_strlcpy
+#else
+#define strlcat strncat
+#define strlcpy strncpy
+#endif
+
+#define UID_GPS (1021)
+#define GID_GPS (1021)
+#define UID_LOCCLIENT (4021)
+#define GID_LOCCLIENT (4021)
+
+#define LOC_PATH_GPS_CONF_STR "/etc/gps.conf"
+#define LOC_PATH_IZAT_CONF_STR "/etc/izat.conf"
+#define LOC_PATH_FLP_CONF_STR "/etc/flp.conf"
+#define LOC_PATH_LOWI_CONF_STR "/etc/lowi.conf"
+#define LOC_PATH_SAP_CONF_STR "/etc/sap.conf"
+#define LOC_PATH_APDR_CONF_STR "/etc/apdr.conf"
+#define LOC_PATH_XTWIFI_CONF_STR "/etc/xtwifi.conf"
+#define LOC_PATH_QUIPC_CONF_STR "/etc/quipc.conf"
+#define LOC_PATH_ANT_CORR_STR "/etc/gnss_antenna_info.conf"
+#define LOC_PATH_SLIM_CONF_STR "/etc/slim.conf"
+#define LOC_PATH_VPE_CONF_STR "/etc/vpeglue.conf"
+
+#ifdef FEATURE_EXTERNAL_AP
+#define PROPERTY_VALUE_MAX 92
+
+inline int property_get(const char* key, char* value, const char* default_value)
+{
+ strlcpy(value, default_value, PROPERTY_VALUE_MAX - 1);
+ return strlen(value);
+}
+#endif /* FEATURE_EXTERNAL_AP */
+
+/*!
+ * @brief Function for memory block copy
+ *
+ * @param[out] p_Dest Destination buffer.
+ * @param[in] q_DestSize Destination buffer size.
+ * @param[in] p_Src Source buffer.
+ * @param[in] q_SrcSize Source buffer size.
+ *
+ * @return Number of bytes copied.
+ */
+static inline size_t memscpy (void *p_Dest, size_t q_DestSize, const void *p_Src, size_t q_SrcSize)
+{
+ size_t res = (q_DestSize < q_SrcSize) ? q_DestSize : q_SrcSize;
+ if (p_Dest && p_Src && q_DestSize > 0 && q_SrcSize > 0) {
+ memcpy(p_Dest, p_Src, res);
+ } else {
+ res = 0;
+ }
+ return res;
+}
+
+/*API for boot kpi marker prints */
+static inline int loc_boot_kpi_marker(const char * pFmt, ...)
+{
+ int result = 0;
+ FILE *stream = NULL;
+ char data[MAX_COMMAND_STR_LEN] = {};
+ char buf[MAX_COMMAND_STR_LEN] = {};
+
+ va_list ap;
+ va_start(ap, pFmt);
+ vsnprintf(&buf[0], sizeof(buf), pFmt, ap);
+ snprintf(data, sizeof(data), "echo -n %s > %s", buf, BOOT_KPI_FILE);
+ stream = popen(data, "w" );
+ if (NULL == stream) {
+ result = -1;
+ } else {
+ pclose(stream);
+ }
+ va_end(ap);
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus */
+
+#endif /* __LOC_PLA__ */
diff --git a/gps/utils/Android.bp b/gps/utils/Android.bp
new file mode 100644
index 0000000..7d43d57
--- /dev/null
+++ b/gps/utils/Android.bp
@@ -0,0 +1,54 @@
+
+cc_library_shared {
+
+ name: "libgps.utils",
+ vendor: true,
+
+ sanitize: GNSS_SANITIZE,
+
+ //# Libs
+ shared_libs: [
+ "libdl",
+ "libutils",
+ "libcutils",
+ "liblog",
+ "libprocessgroup",
+ ],
+
+ srcs: [
+ "loc_log.cpp",
+ "loc_cfg.cpp",
+ "msg_q.c",
+ "linked_list.c",
+ "loc_target.cpp",
+ "LocHeap.cpp",
+ "LocTimer.cpp",
+ "LocThread.cpp",
+ "MsgTask.cpp",
+ "loc_misc_utils.cpp",
+ "loc_nmea.cpp",
+ "LocIpc.cpp",
+ "LogBuffer.cpp",
+ ],
+
+ cflags: [
+ "-fno-short-enums",
+ "-D_ANDROID_",
+ ] + GNSS_CFLAGS,
+
+ //# Includes
+ ldflags: ["-Wl,--export-dynamic"],
+
+ header_libs: [
+ "libutils_headers",
+ "libloc_pla_headers",
+ "liblocation_api_headers",
+ ],
+}
+
+cc_library_headers {
+
+ name: "libgps.utils_headers",
+ export_include_dirs: ["."],
+ vendor: true,
+}
diff --git a/gps/utils/LocHeap.cpp b/gps/utils/LocHeap.cpp
new file mode 100644
index 0000000..4d047e4
--- /dev/null
+++ b/gps/utils/LocHeap.cpp
@@ -0,0 +1,280 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <LocHeap.h>
+
+namespace loc_util {
+
+class LocHeapNode {
+ friend class LocHeap;
+
+ // size of of the subtree, excluding self, 1 if no subtree
+ int mSize;
+ LocHeapNode* mLeft;
+ LocHeapNode* mRight;
+ LocRankable* mData;
+public:
+ inline LocHeapNode(LocRankable& data) :
+ mSize(1), mLeft(NULL), mRight(NULL), mData(&data) {}
+ ~LocHeapNode();
+
+ // this only swaps the data of the two nodes, so no
+ // detach / re-attached is necessary
+ void swap(LocHeapNode& node);
+
+ LocRankable* detachData();
+
+ // push a node into the tree stucture, keeping sorted by rank
+ void push(LocHeapNode& node);
+
+ // pop the head node out of the tree stucture. keeping sorted by rank
+ static LocHeapNode* pop(LocHeapNode*& top);
+
+ // remove a specific node from the tree
+ // returns the pointer to the node removed, which would be either the
+ // same as input (if successfully removed); or NULL (if failed).
+ static LocHeapNode* remove(LocHeapNode*& top, LocRankable& data);
+
+ // convenience method to compare data ranking
+ inline bool outRanks(LocHeapNode& node) { return mData->outRanks(*node.mData); }
+ inline bool outRanks(LocRankable& data) { return mData->outRanks(data); }
+
+ // checks if mSize is correct, AND this node is the highest ranking
+ // of the entire subtree
+ bool checkNodes();
+
+ inline int getSize() { return mSize; }
+};
+
+inline
+LocHeapNode::~LocHeapNode() {
+ if (mLeft) {
+ delete mLeft;
+ mLeft = NULL;
+ }
+ if (mRight) {
+ delete mRight;
+ mRight = NULL;
+ }
+ if (mData) {
+ mData = NULL;
+ }
+}
+
+inline
+void LocHeapNode::swap(LocHeapNode& node) {
+ LocRankable* tmpData = node.mData;
+ node.mData = mData;
+ mData = tmpData;
+}
+
+inline
+LocRankable* LocHeapNode::detachData() {
+ LocRankable* data = mData;
+ mData = NULL;
+ return data;
+}
+
+// push keeps the tree sorted by rank, it also tries to balance the
+// tree by adding the new node to the smaller of the subtrees.
+// The pointer to the tree and internal links never change. If the
+// mData of tree top ranks lower than that of the incoming node,
+// mData will be swapped with that of the incoming node to ensure
+// ranking, no restructuring the container nodes.
+void LocHeapNode::push(LocHeapNode& node) {
+ // ensure the current node ranks higher than in the incoming one
+ if (node.outRanks(*this)) {
+ swap(node);
+ }
+
+ // now drop the new node (ensured lower than *this) into a subtree
+ if (NULL == mLeft) {
+ mLeft = &node;
+ } else if (NULL == mRight) {
+ mRight = &node;
+ } else if (mLeft->mSize <= mRight->mSize) {
+ mLeft->push(node);
+ } else {
+ mRight->push(node);
+ }
+ mSize++;
+}
+
+// pop keeps the tree sorted by rank, but it does not try to balance
+// the tree. It recursively swaps with the higher ranked top of the
+// subtrees.
+// The return is a popped out node from leaf level, that has the data
+// swapped all the way down from the top. The pinter to the tree and
+// internal links will not be changed or restructured, except for the
+// node that is popped out.
+// If the return pointer == this, this the last node in the tree.
+LocHeapNode* LocHeapNode::pop(LocHeapNode*& top) {
+ // we know the top has the highest ranking at this point, else
+ // the tree is broken. This top will be popped out. But we need
+ // a node from the left or right child, whichever ranks higher,
+ // to replace the current top. This then will need to be done
+ // recursively to the leaf level. So we swap the mData of the
+ // current top node all the way down to the leaf level.
+ LocHeapNode* poppedNode = top;
+ // top is losing a node in its subtree
+ top->mSize--;
+ if (top->mLeft || top->mRight) {
+ // if mLeft is NULL, mRight for sure is NOT NULL, take that;
+ // else if mRight is NULL, mLeft for sure is NOT, take that;
+ // else we take the address of whatever has higher ranking mData
+ LocHeapNode*& subTop = (NULL == top->mLeft) ? top->mRight :
+ ((NULL == top->mRight) ? top->mLeft :
+ (top->mLeft->outRanks(*(top->mRight)) ? top->mLeft : top->mRight));
+ // swap mData, the tree top gets updated with the new data.
+ top->swap(*subTop);
+ // pop out from the subtree
+ poppedNode = pop(subTop);
+ } else {
+ // if the top has only single node
+ // detach the poppedNode from the tree
+ // subTop is the reference of ether mLeft or mRight
+ // NOT a local stack pointer. so it MUST be NULL'ed here.
+ top = NULL;
+ }
+
+ return poppedNode;
+}
+
+// navigating through the tree and find the node that hass the input
+// data. Since this is a heap, we do recursive linear search.
+// returns the pointer to the node removed, which would be either the
+// same as input (if successfully removed); or NULL (if failed).
+LocHeapNode* LocHeapNode::remove(LocHeapNode*& top, LocRankable& data) {
+ LocHeapNode* removedNode = NULL;
+ // this is the node, by address
+ if (&data == (LocRankable*)(top->mData)) {
+ // pop this node out
+ removedNode = pop(top);
+ } else if (!data.outRanks(*top->mData)) {
+ // subtrees might have this node
+ if (top->mLeft) {
+ removedNode = remove(top->mLeft, data);
+ }
+ // if we did not find in mLeft, and mRight is not empty
+ if (!removedNode && top->mRight) {
+ removedNode = remove(top->mRight, data);
+ }
+
+ // top lost a node in its subtree
+ if (removedNode) {
+ top->mSize--;
+ }
+ }
+
+ return removedNode;
+}
+
+// checks if mSize is correct, AND this node is the highest ranking
+// of the entire subtree
+bool LocHeapNode::checkNodes() {
+ // size of the current subtree
+ int totalSize = mSize;
+ if (mLeft) {
+ // check the consistency of left subtree
+ if (mLeft->outRanks(*this) || !mLeft->checkNodes()) {
+ return false;
+ }
+ // subtract the size of left subtree (with subtree head)
+ totalSize -= mLeft->mSize;
+ }
+
+ if (mRight) {
+ // check the consistency of right subtree
+ if (mRight->outRanks(*this) || !mRight->checkNodes()) {
+ return false;
+ }
+ // subtract the size of right subtree (with subtree head)
+ totalSize -= mRight->mSize;
+ }
+
+ // for the tree nodes to consistent, totalSize must be 1 now
+ return totalSize == 1;
+}
+
+LocHeap::~LocHeap() {
+ if (mTree) {
+ delete mTree;
+ }
+}
+
+void LocHeap::push(LocRankable& node) {
+ LocHeapNode* heapNode = new LocHeapNode(node);
+ if (!mTree) {
+ mTree = heapNode;
+ } else {
+ mTree->push(*heapNode);
+ }
+}
+
+LocRankable* LocHeap::peek() {
+ LocRankable* top = NULL;
+ if (mTree) {
+ top = mTree->mData;
+ }
+ return top;
+}
+
+LocRankable* LocHeap::pop() {
+ LocRankable* locNode = NULL;
+ if (mTree) {
+ // mTree may become NULL after this call
+ LocHeapNode* heapNode = LocHeapNode::pop(mTree);
+ locNode = heapNode->detachData();
+ delete heapNode;
+ }
+ return locNode;
+}
+
+LocRankable* LocHeap::remove(LocRankable& rankable) {
+ LocRankable* locNode = NULL;
+ if (mTree) {
+ // mTree may become NULL after this call
+ LocHeapNode* heapNode = LocHeapNode::remove(mTree, rankable);
+ if (heapNode) {
+ locNode = heapNode->detachData();
+ delete heapNode;
+ }
+ }
+ return locNode;
+}
+
+} // namespace loc_util
+
+#ifdef __LOC_UNIT_TEST__
+bool LocHeap::checkTree() {
+ return ((NULL == mTree) || mTree->checkNodes());
+}
+uint32_t LocHeap::getTreeSize() {
+ return (NULL == mTree) ? 0 : mTree->getSize();
+}
+#endif
diff --git a/gps/utils/LocHeap.h b/gps/utils/LocHeap.h
new file mode 100644
index 0000000..bb62d6b
--- /dev/null
+++ b/gps/utils/LocHeap.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_HEAP__
+#define __LOC_HEAP__
+
+#include <stddef.h>
+#include <string.h>
+
+namespace loc_util {
+
+// abstract class to be implemented by client to provide a rankable class
+class LocRankable {
+public:
+ virtual inline ~LocRankable() {}
+
+ // method to rank objects of such type for sorting purposes.
+ // The pointer of the input node would be stored in the heap.
+ // >0 if ranks higher than the input;
+ // ==0 if equally ranks with the input;
+ // <0 if ranks lower than the input
+ virtual int ranks(LocRankable& rankable) = 0;
+
+ // convenient method to rank objects of such type for sorting purposes.
+ inline bool outRanks(LocRankable& rankable) { return ranks(rankable) > 0; }
+};
+
+// opaque class to provide service implementation.
+class LocHeapNode;
+
+// a heap whose left and right children are not sorted. It is sorted only vertically,
+// i.e. parent always ranks higher than children, if they exist. Ranking algorithm is
+// implemented in Rankable. The reason that there is no sort between children is to
+// help beter balance the tree with lower cost. When a node is pushed to the tree,
+// it is guaranteed that the subtree that is smaller gets to have the new node.
+class LocHeap {
+protected:
+ LocHeapNode* mTree;
+public:
+ inline LocHeap() : mTree(NULL) {}
+ ~LocHeap();
+
+ // push keeps the tree sorted by rank, it also tries to balance the
+ // tree by adding the new node to the smaller of the subtrees.
+ // node is reference to an obj that is managed by client, that client
+ // creates and destroyes. The destroy should happen after the
+ // node is popped out from the heap.
+ void push(LocRankable& node);
+
+ // Peeks the node data on tree top, which has currently the highest ranking
+ // There is no change the tree structure with this operation
+ // Returns NULL if the tree is empty, otherwise pointer to the node data of
+ // the tree top.
+ LocRankable* peek();
+
+ // pop keeps the tree sorted by rank, but it does not try to balance
+ // the tree.
+ // Return - pointer to the node popped out, or NULL if heap is already empty
+ LocRankable* pop();
+
+ // navigating through the tree and find the node that ranks the same
+ // as the input data, then remove it from the tree. Rank is implemented
+ // by rankable obj.
+ // returns the pointer to the node removed; or NULL (if failed).
+ LocRankable* remove(LocRankable& rankable);
+
+#ifdef __LOC_UNIT_TEST__
+ bool checkTree();
+ uint32_t getTreeSize();
+#endif
+};
+
+} // namespace loc_util
+
+#endif //__LOC_HEAP__
diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp
new file mode 100644
index 0000000..746ca87
--- /dev/null
+++ b/gps/utils/LocIpc.cpp
@@ -0,0 +1,430 @@
+/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <loc_misc_utils.h>
+#include <log_util.h>
+#include <LocIpc.h>
+#include <algorithm>
+
+using namespace std;
+
+namespace loc_util {
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "LocSvc_LocIpc"
+
+#define SOCK_OP_AND_LOG(buf, length, opable, rtv, exe) \
+ if (nullptr == (buf) || 0 == (length)) { \
+ LOC_LOGe("Invalid inputs: buf - %p, length - %u", (buf), (length)); \
+ } else if (!(opable)) { \
+ LOC_LOGe("Invalid object: operable - %d", (opable)); \
+ } else { \
+ rtv = (exe); \
+ if (-1 == rtv) { \
+ LOC_LOGw("failed reason: %s", strerror(errno)); \
+ } \
+ }
+
+const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT";
+const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$";
+ssize_t Sock::send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const {
+ ssize_t rtv = -1;
+ SOCK_OP_AND_LOG(buf, len, isValid(), rtv, sendto(buf, len, flags, destAddr, addrlen));
+ return rtv;
+}
+ssize_t Sock::recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
+ struct sockaddr *srcAddr, socklen_t *addrlen, int sid) const {
+ ssize_t rtv = -1;
+ if (-1 == sid) {
+ sid = mSid;
+ } // else it sid would be connection based socket id for recv
+ SOCK_OP_AND_LOG(dataCb.get(), mMaxTxSize, isValid(), rtv,
+ recvfrom(recver, dataCb, sid, flags, srcAddr, addrlen));
+ return rtv;
+}
+ssize_t Sock::sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const {
+ ssize_t rtv = -1;
+ if (len <= mMaxTxSize) {
+ rtv = ::sendto(mSid, buf, len, flags, destAddr, addrlen);
+ } else {
+ std::string head(LOC_IPC_HEAD + to_string(len));
+ rtv = ::sendto(mSid, head.c_str(), head.length(), flags, destAddr, addrlen);
+ if (rtv > 0) {
+ for (size_t offset = 0; offset < len && rtv > 0; offset += rtv) {
+ rtv = ::sendto(mSid, (char*)buf + offset, min(len - offset, (size_t)mMaxTxSize),
+ flags, destAddr, addrlen);
+ }
+ rtv = (rtv > 0) ? (head.length() + len) : -1;
+ }
+ }
+ return rtv;
+}
+ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
+ int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const {
+ std::string msg(mMaxTxSize, 0);
+ ssize_t nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen);
+ if (nBytes > 0) {
+ if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) {
+ LOC_LOGi("recvd abort msg.data %s", msg.data());
+ nBytes = 0;
+ } else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) {
+ // short message
+ msg.resize(nBytes);
+ dataCb->onReceive(msg.data(), nBytes, &recver);
+ } else {
+ // long message
+ size_t msgLen = 0;
+ sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen);
+ msg.resize(msgLen);
+ for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0);
+ msgLenReceived += nBytes) {
+ nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived,
+ flags, srcAddr, addrlen);
+ }
+ if (nBytes > 0) {
+ nBytes = msgLen;
+ dataCb->onReceive(msg.data(), nBytes, &recver);
+ }
+ }
+ }
+
+ return nBytes;
+}
+ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) {
+ return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen);
+}
+
+class LocIpcLocalSender : public LocIpcSender {
+protected:
+ shared_ptr<Sock> mSock;
+ struct sockaddr_un mAddr;
+ inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
+ inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+public:
+ inline LocIpcLocalSender(const char* name) : LocIpcSender(),
+ mSock(nullptr),
+ mAddr({.sun_family = AF_UNIX, {}}) {
+
+ int fd = -1;
+ if (nullptr != name) {
+ fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd >= 0) {
+ timeval timeout;
+ timeout.tv_sec = 2;
+ timeout.tv_usec = 0;
+ setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
+ }
+ }
+ mSock.reset(new Sock(fd));
+ if (mSock != nullptr && mSock->isValid()) {
+ snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
+ }
+ }
+};
+
+class LocIpcLocalRecver : public LocIpcLocalSender, public LocIpcRecver {
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
+ }
+public:
+ inline LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) :
+ LocIpcLocalSender(name), LocIpcRecver(listener, *this) {
+
+ if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) {
+ LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
+ }
+
+ umask(0157);
+ if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
+ LOC_LOGe("bind socket error. sock fd: %d: %s, reason: %s", mSock->mSid,
+ mAddr.sun_path, strerror(errno));
+ mSock->close();
+ }
+ }
+ inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
+ inline virtual const char* getName() const override { return mAddr.sun_path; };
+ inline virtual void abort() const override {
+ if (isSendable()) {
+ mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+ }
+};
+
+class LocIpcInetSender : public LocIpcSender {
+protected:
+ int mSockType;
+ shared_ptr<Sock> mSock;
+ const string mName;
+ sockaddr_in mAddr;
+ inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
+ virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+public:
+ inline LocIpcInetSender(const LocIpcInetSender& sender) :
+ mSockType(sender.mSockType), mSock(sender.mSock),
+ mName(sender.mName), mAddr(sender.mAddr) {
+ }
+ inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(),
+ mSockType(sockType),
+ mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))),
+ mName((nullptr == name) ? "" : name),
+ mAddr({.sin_family = AF_INET, .sin_port = htons(port),
+ .sin_addr = {htonl(INADDR_ANY)}}) {
+ if (mSock != nullptr && mSock->isValid() && nullptr != name) {
+ struct hostent* hp = gethostbyname(name);
+ if (nullptr != hp) {
+ memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
+ }
+ }
+ }
+
+ unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
+ return make_unique<SockRecver>(listener, *this, mSock);
+ }
+};
+
+class LocIpcInetTcpSender : public LocIpcInetSender {
+protected:
+ mutable bool mFirstTime;
+
+ virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
+ if (mFirstTime) {
+ mFirstTime = false;
+ ::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+ return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
+ }
+
+public:
+ inline LocIpcInetTcpSender(const char* name, int32_t port) :
+ LocIpcInetSender(name, port, SOCK_STREAM),
+ mFirstTime(true) {}
+};
+
+class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver {
+ int32_t mPort;
+protected:
+ virtual ssize_t recv() const = 0;
+public:
+ inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port, int sockType) :
+ LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this),
+ mPort(port) {
+ if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
+ LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
+ mSock->close();
+ }
+ }
+ inline virtual ~LocIpcInetRecver() {}
+ inline virtual const char* getName() const override { return mName.data(); };
+ inline virtual void abort() const override {
+ if (isSendable()) {
+ sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort),
+ .sin_addr = {htonl(INADDR_LOOPBACK)}};
+ mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr));
+ }
+ }
+ inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
+ return make_unique<LocIpcInetSender>(static_cast<const LocIpcInetSender&>(*this));
+ }
+};
+
+class LocIpcInetTcpRecver : public LocIpcInetRecver {
+ mutable int32_t mConnFd;
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ if (-1 == mConnFd && mSock->isValid()) {
+ if (::listen(mSock->mSid, 3) < 0 ||
+ (mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
+ mSock->close();
+ mConnFd = -1;
+ }
+ }
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
+ }
+public:
+ inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port) :
+ LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {}
+ inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);}
+};
+
+class LocIpcInetUdpRecver : public LocIpcInetRecver {
+protected:
+ inline virtual ssize_t recv() const override {
+ socklen_t size = sizeof(mAddr);
+ return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
+ }
+public:
+ inline LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
+ int32_t port) :
+ LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {}
+
+ inline virtual ~LocIpcInetUdpRecver() {}
+};
+
+class LocIpcRunnable : public LocRunnable {
+ bool mAbortCalled;
+ LocIpc& mLocIpc;
+ unique_ptr<LocIpcRecver> mIpcRecver;
+public:
+ inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
+ mAbortCalled(false),
+ mLocIpc(locIpc),
+ mIpcRecver(move(ipcRecver)) {}
+ inline virtual bool run() override {
+ if (mIpcRecver != nullptr) {
+ mLocIpc.startBlockingListening(*(mIpcRecver.get()));
+ if (!mAbortCalled) {
+ LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
+ }
+ }
+ // return false so the calling thread exits while loop
+ return false;
+ }
+ inline virtual void interrupt() override {
+ mAbortCalled = true;
+ if (mIpcRecver != nullptr) {
+ mIpcRecver->abort();
+ }
+ }
+};
+
+bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
+ if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
+ std::string threadName("LocIpc-");
+ threadName.append(ipcRecver->getName());
+ return mThread.start(threadName.c_str(), make_shared<LocIpcRunnable>(*this, ipcRecver));
+ } else {
+ LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
+ return false;
+ }
+}
+
+bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
+ if (ipcRecver.isRecvable()) {
+ // inform that the socket is ready to receive message
+ ipcRecver.onListenerReady();
+ while (ipcRecver.recvData());
+ return true;
+ } else {
+ LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
+ return false;
+ }
+}
+
+void LocIpc::stopNonBlockingListening() {
+ mThread.stop();
+}
+
+void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
+ if (ipcRecver.isRecvable()) {
+ ipcRecver.abort();
+ }
+}
+
+bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
+ return sender.sendData(data, length, msgId);
+}
+
+shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
+ return make_shared<LocIpcLocalSender>(localSockName);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* localSockName) {
+ return make_unique<LocIpcLocalRecver>(listener, localSockName);
+}
+static void* sLibQrtrHandle = nullptr;
+static const char* sLibQrtrName = "libloc_socket.so";
+shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
+ typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
+ "_ZN8loc_util22createLocIpcQrtrSenderEii");
+ return (nullptr == creator) ? nullptr : creator(service, instance);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
+ int service, int instance,
+ const shared_ptr<LocIpcQrtrWatcher>& watcher) {
+ typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int,
+ const shared_ptr<LocIpcQrtrWatcher>& watcher);
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
+#ifdef USE_GLIB
+ "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEiiRKS0_INS_17LocIpcQrtrWatcherEE");
+#else
+ "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEiiRKNS1_INS_17LocIpcQrtrWatcherEEE");
+#endif
+ return (nullptr == creator) ? nullptr : creator(listener, service, instance, watcher);
+}
+shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
+ return make_shared<LocIpcInetTcpSender>(serverName, port);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port) {
+ return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
+}
+shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) {
+ return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM);
+}
+unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port) {
+ return make_unique<LocIpcInetUdpRecver>(listener, serverName, port);
+}
+pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
+ LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
+ typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
+ static void* sLibEmuHandle = nullptr;
+ static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
+#ifdef USE_GLIB
+ "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
+ "ERKSt10shared_ptrIN8loc_util15ILocIpcListenerEEi");
+#else
+ "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
+ "ERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
+#endif
+ return (nullptr == creator) ?
+ make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
+ creator(listener, instance);
+}
+
+}
diff --git a/gps/utils/LocIpc.h b/gps/utils/LocIpc.h
new file mode 100644
index 0000000..b2586e6
--- /dev/null
+++ b/gps/utils/LocIpc.h
@@ -0,0 +1,241 @@
+/* Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __LOC_IPC__
+#define __LOC_IPC__
+
+#include <string>
+#include <memory>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unordered_set>
+#include <mutex>
+#include <LocThread.h>
+
+using namespace std;
+
+namespace loc_util {
+
+class LocIpcRecver;
+class LocIpcSender;
+
+class ILocIpcListener {
+protected:
+ inline virtual ~ILocIpcListener() {}
+public:
+ // LocIpc client can overwrite this function to get notification
+ // when the socket for LocIpc is ready to receive messages.
+ inline virtual void onListenerReady() {}
+ virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0;
+};
+
+class LocIpcQrtrWatcher {
+ const unordered_set<int> mServicesToWatch;
+ unordered_set<int> mClientsToWatch;
+ mutex mMutex;
+ inline bool isInWatch(const unordered_set<int>& idsToWatch, int id) {
+ return idsToWatch.find(id) != idsToWatch.end();
+ }
+protected:
+ inline virtual ~LocIpcQrtrWatcher() {}
+ inline LocIpcQrtrWatcher(unordered_set<int> servicesToWatch)
+ : mServicesToWatch(servicesToWatch) {}
+public:
+ enum class ServiceStatus { UP, DOWN };
+ inline bool isServiceInWatch(int serviceId) {
+ return isInWatch(mServicesToWatch, serviceId);
+ }
+ inline bool isClientInWatch(int nodeId) {
+ lock_guard<mutex> lock(mMutex);
+ return isInWatch(mClientsToWatch, nodeId);
+ }
+ inline void addClientToWatch(int nodeId) {
+ lock_guard<mutex> lock(mMutex);
+ mClientsToWatch.emplace(nodeId);
+ }
+ virtual void onServiceStatusChange(int sericeId, int instanceId, ServiceStatus status,
+ const LocIpcSender& sender) = 0;
+ inline virtual void onClientGone(int nodeId, int portId) {}
+ inline const unordered_set<int>& getServicesToWatch() { return mServicesToWatch; }
+};
+
+class LocIpc {
+public:
+ inline LocIpc() = default;
+ inline virtual ~LocIpc() {
+ stopNonBlockingListening();
+ }
+
+ static shared_ptr<LocIpcSender>
+ getLocIpcLocalSender(const char* localSockName);
+ static shared_ptr<LocIpcSender>
+ getLocIpcInetUdpSender(const char* serverName, int32_t port);
+ static shared_ptr<LocIpcSender>
+ getLocIpcInetTcpSender(const char* serverName, int32_t port);
+ static shared_ptr<LocIpcSender>
+ getLocIpcQrtrSender(int service, int instance);
+
+ static unique_ptr<LocIpcRecver>
+ getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* localSockName);
+ static unique_ptr<LocIpcRecver>
+ getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port);
+ static unique_ptr<LocIpcRecver>
+ getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
+ const char* serverName, int32_t port);
+ inline static unique_ptr<LocIpcRecver>
+ getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
+ int service, int instance) {
+ const shared_ptr<LocIpcQrtrWatcher> qrtrWatcher = nullptr;
+ return getLocIpcQrtrRecver(listener, service, instance, qrtrWatcher);
+ }
+ static unique_ptr<LocIpcRecver>
+ getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
+ int service, int instance,
+ const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher);
+
+ static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
+ getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener,
+ int instance);
+
+ // Listen for new messages in current thread. Calling this funciton will
+ // block current thread.
+ // The listening can be stopped by calling stopBlockingListening() passing
+ // in the same ipcRecver obj handle.
+ static bool startBlockingListening(LocIpcRecver& ipcRecver);
+ static void stopBlockingListening(LocIpcRecver& ipcRecver);
+
+ // Create a new LocThread and listen for new messages in it.
+ // Calling this function will return immediately and won't block current thread.
+ // The listening can be stopped by calling stopNonBlockingListening().
+ bool startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver);
+ void stopNonBlockingListening();
+
+ // Send out a message.
+ // Call this function to send a message in argument data to socket in argument name.
+ //
+ // Argument name contains the name of the target unix socket. data contains the
+ // message to be sent out. Convert your message to a string before calling this function.
+ // The function will return true on success, and false on failure.
+ static bool send(LocIpcSender& sender, const uint8_t data[],
+ uint32_t length, int32_t msgId = -1);
+
+private:
+ LocThread mThread;
+};
+
+/* this is only when client needs to implement Sender / Recver that are not already provided by
+ the factor methods prvoided by LocIpc. */
+
+class LocIpcSender {
+protected:
+ LocIpcSender() = default;
+ virtual bool isOperable() const = 0;
+ virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0;
+public:
+ virtual ~LocIpcSender() = default;
+ inline bool isSendable() const { return isOperable(); }
+ inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const {
+ return isSendable() && (send(data, length, msgId) > 0);
+ }
+ virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) {
+ return nullptr;
+ }
+ inline virtual void copyDestAddrFrom(const LocIpcSender& otherSender) {}
+};
+
+class LocIpcRecver {
+ LocIpcSender& mIpcSender;
+protected:
+ const shared_ptr<ILocIpcListener> mDataCb;
+ inline LocIpcRecver(const shared_ptr<ILocIpcListener>& listener, LocIpcSender& sender) :
+ mIpcSender(sender), mDataCb(listener) {}
+ LocIpcRecver(LocIpcRecver const& recver) = delete;
+ LocIpcRecver& operator=(LocIpcRecver const& recver) = delete;
+ virtual ssize_t recv() const = 0;
+public:
+ virtual ~LocIpcRecver() = default;
+ inline bool recvData() const { return isRecvable() && (recv() > 0); }
+ inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); }
+ virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); }
+ inline virtual unique_ptr<LocIpcSender> getLastSender() const {
+ return nullptr;
+ }
+ virtual void abort() const = 0;
+ virtual const char* getName() const = 0;
+};
+
+class Sock {
+ static const char MSG_ABORT[];
+ static const char LOC_IPC_HEAD[];
+ const uint32_t mMaxTxSize;
+ ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const;
+ ssize_t recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
+ int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const;
+public:
+ int mSid;
+ inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {}
+ inline ~Sock() { close(); }
+ inline bool isValid() const { return -1 != mSid; }
+ ssize_t send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
+ socklen_t addrlen) const;
+ ssize_t recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
+ struct sockaddr *srcAddr, socklen_t *addrlen, int sid = -1) const;
+ ssize_t sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen);
+ inline void close() {
+ if (isValid()) {
+ ::close(mSid);
+ mSid = -1;
+ }
+ }
+};
+
+class SockRecver : public LocIpcRecver {
+ shared_ptr<Sock> mSock;
+protected:
+ inline virtual ssize_t recv() const override {
+ return mSock->recv(*this, mDataCb, 0, nullptr, nullptr);
+ }
+public:
+ inline SockRecver(const shared_ptr<ILocIpcListener>& listener,
+ LocIpcSender& sender, shared_ptr<Sock> sock) :
+ LocIpcRecver(listener, sender), mSock(sock) {
+ }
+ inline virtual const char* getName() const override {
+ return "SockRecver";
+ }
+ inline virtual void abort() const override {}
+};
+
+}
+
+#endif //__LOC_IPC__
diff --git a/gps/utils/LocLoggerBase.h b/gps/utils/LocLoggerBase.h
new file mode 100644
index 0000000..867b6e2
--- /dev/null
+++ b/gps/utils/LocLoggerBase.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef LOC_LOGGER_BASE_H
+#define LOC_LOGGER_BASE_H
+
+namespace loc_util {
+class LocLoggerBase {
+public:
+ virtual void log() {}
+};
+}
+
+#endif
diff --git a/gps/utils/LocSharedLock.h b/gps/utils/LocSharedLock.h
new file mode 100644
index 0000000..1ef2c57
--- /dev/null
+++ b/gps/utils/LocSharedLock.h
@@ -0,0 +1,81 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_SHARED_LOCK__
+#define __LOC_SHARED_LOCK__
+
+#include <stddef.h>
+#ifndef FEATURE_EXTERNAL_AP
+#include <cutils/atomic.h>
+#endif /* FEATURE_EXTERNAL_AP */
+#include <pthread.h>
+
+#ifdef FEATURE_EXTERNAL_AP
+#include <atomic>
+
+inline int32_t android_atomic_inc(volatile int32_t *addr)
+{
+ volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr;
+ return std::atomic_fetch_add_explicit(a, 1, std::memory_order_release);
+}
+
+inline int32_t android_atomic_dec(volatile int32_t *addr)
+{
+ volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr;
+ return std::atomic_fetch_sub_explicit(a, 1, std::memory_order_release);
+}
+#endif /* FEATURE_EXTERNAL_AP */
+
+namespace loc_util {
+
+// This is a utility created for use cases such that there are more than
+// one client who need to share the same lock, but it is not predictable
+// which of these clients is to last to go away. This shared lock deletes
+// itself when the last client calls its drop() method. To add a cient,
+// this share lock's share() method has to be called, so that the obj
+// can maintain an accurate client count.
+class LocSharedLock {
+ volatile int32_t mRef;
+ pthread_mutex_t mMutex;
+ inline ~LocSharedLock() { pthread_mutex_destroy(&mMutex); }
+public:
+ // first client to create this LockSharedLock
+ inline LocSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); }
+ // following client(s) are to *share()* this lock created by the first client
+ inline LocSharedLock* share() { android_atomic_inc(&mRef); return this; }
+ // whe a client no longer needs this shared lock, drop() shall be called.
+ inline void drop() { if (1 == android_atomic_dec(&mRef)) delete this; }
+ // locking the lock to enter critical section
+ inline void lock() { pthread_mutex_lock(&mMutex); }
+ // unlocking the lock to leave the critical section
+ inline void unlock() { pthread_mutex_unlock(&mMutex); }
+};
+
+} //namespace loc_util
+
+#endif //__LOC_SHARED_LOCK__
diff --git a/gps/utils/LocThread.cpp b/gps/utils/LocThread.cpp
new file mode 100644
index 0000000..3cac1f9
--- /dev/null
+++ b/gps/utils/LocThread.cpp
@@ -0,0 +1,111 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <sys/prctl.h>
+#include <LocThread.h>
+#include <string.h>
+#include <string>
+#include <thread>
+#include <loc_pla.h>
+
+using std::weak_ptr;
+using std::shared_ptr;
+using std::thread;
+using std::string;
+
+namespace loc_util {
+
+class LocThreadDelegate {
+ static const char defaultThreadName[];
+ weak_ptr<LocRunnable> mRunnable;
+ thread mThread;
+ LocThreadDelegate(const string tName, shared_ptr<LocRunnable> r);
+public:
+ ~LocThreadDelegate() {
+ shared_ptr<LocRunnable> runnable = mRunnable.lock();
+ if (nullptr != runnable) {
+ runnable->interrupt();
+ }
+ }
+ inline static LocThreadDelegate* create(const char* tName, shared_ptr<LocRunnable> runnable);
+};
+
+const char LocThreadDelegate::defaultThreadName[] = "LocThread";
+
+LocThreadDelegate* LocThreadDelegate::create(const char* tName, shared_ptr<LocRunnable> runnable) {
+ LocThreadDelegate* threadDelegate = nullptr;
+
+ if (nullptr != runnable) {
+ if (!tName) {
+ tName = defaultThreadName;
+ }
+
+ char lname[16];
+ auto nameSize = strlen(tName) + 1;
+ int len = std::min(sizeof(lname), nameSize) - 1;
+ memcpy(lname, tName, len);
+ lname[len] = 0;
+
+ threadDelegate = new LocThreadDelegate(lname, runnable);
+ }
+
+ return threadDelegate;
+}
+
+LocThreadDelegate::LocThreadDelegate(const string tName, shared_ptr<LocRunnable> runnable) :
+ mRunnable(runnable),
+ mThread([tName, runnable] {
+ prctl(PR_SET_NAME, tName.c_str(), 0, 0, 0);
+ runnable->prerun();
+ while (runnable->run());
+ runnable->postrun();
+ }) {
+
+ mThread.detach();
+}
+
+
+
+bool LocThread::start(const char* tName, shared_ptr<LocRunnable> runnable) {
+ bool success = false;
+ if (!mThread) {
+ mThread = LocThreadDelegate::create(tName, runnable);
+ // true only if thread is created successfully
+ success = (NULL != mThread);
+ }
+ return success;
+}
+
+void LocThread::stop() {
+ if (nullptr != mThread) {
+ delete mThread;
+ mThread = nullptr;
+ }
+}
+
+} // loc_util
diff --git a/gps/utils/LocThread.h b/gps/utils/LocThread.h
new file mode 100644
index 0000000..c7ece87
--- /dev/null
+++ b/gps/utils/LocThread.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_THREAD__
+#define __LOC_THREAD__
+
+#include <stddef.h>
+#include <memory>
+
+using std::shared_ptr;
+
+namespace loc_util {
+
+// abstract class to be implemented by client to provide a runnable class
+// which gets scheduled by LocThread
+class LocRunnable {
+public:
+ inline LocRunnable() = default;
+ inline virtual ~LocRunnable() = default;
+
+ // The method to be implemented by thread clients
+ // and be scheduled by LocThread
+ // This method will be repeated called until it returns false; or
+ // until thread is stopped.
+ virtual bool run() = 0;
+
+ // The method to be run before thread loop (conditionally repeatedly)
+ // calls run()
+ inline virtual void prerun() {}
+
+ // The method to be run after thread loop (conditionally repeatedly)
+ // calls run()
+ inline virtual void postrun() {}
+
+ // The method to wake up the potential blocking thread
+ // no op if not applicable
+ inline virtual void interrupt() = 0;
+};
+
+// opaque class to provide service implementation.
+class LocThreadDelegate;
+
+// A utility class to create a thread and run LocRunnable
+// caller passes in.
+class LocThread {
+ LocThreadDelegate* mThread;
+public:
+ inline LocThread() : mThread(NULL) {}
+ inline virtual ~LocThread() { stop(); }
+
+ // client starts thread with a runnable, which implements
+ // the logics to fun in the created thread context.
+ // The thread is always detached.
+ // runnable is an obj managed by client. Client creates and
+ // frees it (but must be after stop() is called, or
+ // this LocThread obj is deleted).
+ // The obj will be deleted by LocThread if start()
+ // returns true. Else it is client's responsibility
+ // to delete the object
+ // Returns 0 if success; false if failure.
+ bool start(const char* threadName, shared_ptr<LocRunnable> runnable);
+
+ void stop();
+
+ // thread status check
+ inline bool isRunning() { return NULL != mThread; }
+};
+
+} // loc_util
+#endif //__LOC_THREAD__
diff --git a/gps/utils/LocTimer.cpp b/gps/utils/LocTimer.cpp
new file mode 100644
index 0000000..915cf54
--- /dev/null
+++ b/gps/utils/LocTimer.cpp
@@ -0,0 +1,648 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/timerfd.h>
+#include <sys/epoll.h>
+#include <log_util.h>
+#include <loc_timer.h>
+#include <LocTimer.h>
+#include <LocHeap.h>
+#include <LocThread.h>
+#include <LocSharedLock.h>
+#include <MsgTask.h>
+
+#ifdef __HOST_UNIT_TEST__
+#define EPOLLWAKEUP 0
+#define CLOCK_BOOTTIME CLOCK_MONOTONIC
+#define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC
+#endif
+
+namespace loc_util {
+
+/*
+There are implementations of 5 classes in this file:
+LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper
+
+LocTimer - client front end, interface for client to start / stop timers, also
+ to provide a callback.
+LocTimerDelegate - an internal timer entity, which also is a LocRankable obj.
+ Its life cycle is different than that of LocTimer. It gets
+ created when LocTimer::start() is called, and gets deleted
+ when it expires or clients calls the hosting LocTimer obj's
+ stop() method. When a LocTimerDelegate obj is ticking, it
+ stays in the corresponding LocTimerContainer. When expired
+ or stopped, the obj is removed from the container. Since it
+ is also a LocRankable obj, and LocTimerContainer also is a
+ heap, its ranks() implementation decides where it is placed
+ in the heap.
+LocTimerContainer - core of the timer service. It is a container (derived from
+ LocHeap) for LocTimerDelegate (implements LocRankable) objs.
+ There are 2 of such containers, one for sw timers (or Linux
+ timers) one for hw timers (or Linux alarms). It adds one of
+ each (those that expire the soonest) to kernel via services
+ provided by LocTimerPollTask. All the heap management on the
+ LocTimerDelegate objs are done in the MsgTask context, such
+ that synchronization is ensured.
+LocTimerPollTask - is a class that wraps timerfd and epoll POXIS APIs. It also
+ both implements LocRunnalbe with epoll_wait() in the run()
+ method. It is also a LocThread client, so as to loop the run
+ method.
+LocTimerWrapper - a LocTimer client itself, to implement the existing C API with
+ APIs, loc_timer_start() and loc_timer_stop().
+
+*/
+
+class LocTimerPollTask;
+
+// This is a multi-functaional class that:
+// * extends the LocHeap class for the detection of head update upon add / remove
+// events. When that happens, soonest time out changes, so timerfd needs update.
+// * contains the timers, and add / remove them into the heap
+// * provides and maps 2 of such containers, one for timers (or mSwTimers), one
+// for alarms (or mHwTimers);
+// * provides a polling thread;
+// * provides a MsgTask thread for synchronized add / remove / timer client callback.
+class LocTimerContainer : public LocHeap {
+ // mutex to synchronize getters of static members
+ static pthread_mutex_t mMutex;
+ // Container of timers
+ static LocTimerContainer* mSwTimers;
+ // Container of alarms
+ static LocTimerContainer* mHwTimers;
+ // Msg task to provider msg Q, sender and reader.
+ static MsgTask* mMsgTask;
+ // Poll task to provide epoll call and threading to poll.
+ static LocTimerPollTask* mPollTask;
+ // timer / alarm fd
+ int mDevFd;
+ // ctor
+ LocTimerContainer(bool wakeOnExpire);
+ // dtor
+ ~LocTimerContainer();
+ static MsgTask* getMsgTaskLocked();
+ static LocTimerPollTask* getPollTaskLocked();
+ // extend LocHeap and pop if the top outRanks input
+ LocTimerDelegate* popIfOutRanks(LocTimerDelegate& timer);
+ // update the timer POSIX calls with updated soonest timer spec
+ void updateSoonestTime(LocTimerDelegate* priorTop);
+
+public:
+ // factory method to control the creation of mSwTimers / mHwTimers
+ static LocTimerContainer* get(bool wakeOnExpire);
+
+ LocTimerDelegate* getSoonestTimer();
+ int getTimerFd();
+ // add a timer / alarm obj into the container
+ void add(LocTimerDelegate& timer);
+ // remove a timer / alarm obj from the container
+ void remove(LocTimerDelegate& timer);
+ // handling of timer / alarm expiration
+ void expire();
+};
+
+class TimerRunnable : public LocRunnable {
+ const int mFd;
+public:
+ inline TimerRunnable(const int fd) : mFd(fd) {}
+ // The method to be implemented by thread clients
+ // and be scheduled by LocThread
+ // This method will be repeated called until it returns false; or
+ // until thread is stopped.
+ virtual bool run() override;
+
+ // The method to wake up the potential blocking thread
+ // no op if not applicable
+ inline virtual void interrupt() { close(mFd); }
+};
+
+// This class implements the polling thread that epolls imer / alarm fds.
+// The LocRunnable::run() contains the actual polling. The other methods
+// will be run in the caller's thread context to add / remove timer / alarm
+// fds the kernel, while the polling is blocked on epoll_wait() call.
+// Since the design is that we have maximally 2 polls, one for all the
+// timers; one for all the alarms, we will poll at most on 2 fds. But it
+// is possile that all we have are only timers or alarms at one time, so we
+// allow dynamically add / remove fds we poll on. The design decision of
+// having 1 fd per container of timer / alarm is such that, we may not need
+// to make a system call each time a timer / alarm is added / removed, unless
+// that changes the "soonest" time out of that of all the timers / alarms.
+class LocTimerPollTask {
+ // the epoll fd
+ const int mFd;
+ // the thread that calls TimerRunnable::run() method, where
+ // epoll_wait() is blocking and waiting for events..
+ LocThread mThread;
+public:
+ // ctor
+ LocTimerPollTask();
+ // dtor
+ ~LocTimerPollTask() = default;
+ // add a container of timers. Each contain has a unique device fd, i.e.
+ // either timer or alarm fd, and a heap of timers / alarms. It is expected
+ // that container would have written to the device fd with the soonest
+ // time out value in the heap at the time of calling this method. So all
+ // this method does is to add the fd of the input container to the poll
+ // and also add the pointer of the container to the event data ptr, such
+ // when poll_wait wakes up on events, we know who is the owner of the fd.
+ void addPoll(LocTimerContainer& timerContainer);
+ // remove a fd that is assciated with a container. The expectation is that
+ // the atual timer would have been removed from the container.
+ void removePoll(LocTimerContainer& timerContainer);
+};
+
+// Internal class of timer obj. It gets born when client calls LocTimer::start();
+// and gets deleted when client calls LocTimer::stop() or when the it expire()'s.
+// This class implements LocRankable::ranks() so that when an obj is added into
+// the container (of LocHeap), it gets placed in sorted order.
+class LocTimerDelegate : public LocRankable {
+ friend class LocTimerContainer;
+ friend class LocTimer;
+ LocTimer* mClient;
+ LocSharedLock* mLock;
+ struct timespec mFutureTime;
+ LocTimerContainer* mContainer;
+ // not a complete obj, just ctor for LocRankable comparisons
+ inline LocTimerDelegate(struct timespec& delay)
+ : mClient(NULL), mLock(NULL), mFutureTime(delay), mContainer(NULL) {}
+ inline ~LocTimerDelegate() { if (mLock) { mLock->drop(); mLock = NULL; } }
+public:
+ LocTimerDelegate(LocTimer& client, struct timespec& futureTime, LocTimerContainer* container);
+ void destroyLocked();
+ // LocRankable virtual method
+ virtual int ranks(LocRankable& rankable);
+ void expire();
+ inline struct timespec getFutureTime() { return mFutureTime; }
+};
+
+/***************************LocTimerContainer methods***************************/
+
+// Most of these static recources are created on demand. They however are never
+// destoyed. The theory is that there are processes that link to this util lib
+// but never use timer, then these resources would never need to be created.
+// For those processes that do use timer, it will likely also need to every
+// once in a while. It might be cheaper keeping them around.
+pthread_mutex_t LocTimerContainer::mMutex = PTHREAD_MUTEX_INITIALIZER;
+LocTimerContainer* LocTimerContainer::mSwTimers = NULL;
+LocTimerContainer* LocTimerContainer::mHwTimers = NULL;
+MsgTask* LocTimerContainer::mMsgTask = NULL;
+LocTimerPollTask* LocTimerContainer::mPollTask = NULL;
+
+// ctor - initialize timer heaps
+// A container for swTimer (timer) is created, when wakeOnExpire is true; or
+// HwTimer (alarm), when wakeOnExpire is false.
+LocTimerContainer::LocTimerContainer(bool wakeOnExpire) :
+ mDevFd(timerfd_create(wakeOnExpire ? CLOCK_BOOTTIME_ALARM : CLOCK_BOOTTIME, 0)) {
+
+ if ((-1 == mDevFd) && (errno == EINVAL)) {
+ LOC_LOGW("%s: timerfd_create failure, fallback to CLOCK_MONOTONIC - %s",
+ __FUNCTION__, strerror(errno));
+ mDevFd = timerfd_create(CLOCK_MONOTONIC, 0);
+ }
+
+ if (-1 != mDevFd) {
+ // ensure we have the necessary resources created
+ LocTimerContainer::getPollTaskLocked();
+ LocTimerContainer::getMsgTaskLocked();
+ } else {
+ LOC_LOGE("%s: timerfd_create failure - %s", __FUNCTION__, strerror(errno));
+ }
+}
+
+// dtor
+// we do not ever destroy the static resources.
+inline
+LocTimerContainer::~LocTimerContainer() {
+ close(mDevFd);
+}
+
+LocTimerContainer* LocTimerContainer::get(bool wakeOnExpire) {
+ // get the reference of either mHwTimer or mSwTimers per wakeOnExpire
+ LocTimerContainer*& container = wakeOnExpire ? mHwTimers : mSwTimers;
+ // it is cheap to check pointer first than locking mutext unconditionally
+ if (!container) {
+ pthread_mutex_lock(&mMutex);
+ // let's check one more time to be safe
+ if (!container) {
+ container = new LocTimerContainer(wakeOnExpire);
+ // timerfd_create failure
+ if (-1 == container->getTimerFd()) {
+ delete container;
+ container = NULL;
+ }
+ }
+ pthread_mutex_unlock(&mMutex);
+ }
+ return container;
+}
+
+MsgTask* LocTimerContainer::getMsgTaskLocked() {
+ // it is cheap to check pointer first than locking mutext unconditionally
+ if (!mMsgTask) {
+ mMsgTask = new MsgTask("LocTimerMsgTask");
+ }
+ return mMsgTask;
+}
+
+LocTimerPollTask* LocTimerContainer::getPollTaskLocked() {
+ // it is cheap to check pointer first than locking mutext unconditionally
+ if (!mPollTask) {
+ mPollTask = new LocTimerPollTask();
+ }
+ return mPollTask;
+}
+
+inline
+LocTimerDelegate* LocTimerContainer::getSoonestTimer() {
+ return (LocTimerDelegate*)(peek());
+}
+
+inline
+int LocTimerContainer::getTimerFd() {
+ return mDevFd;
+}
+
+void LocTimerContainer::updateSoonestTime(LocTimerDelegate* priorTop) {
+ LocTimerDelegate* curTop = getSoonestTimer();
+
+ // check if top has changed
+ if (curTop != priorTop) {
+ struct itimerspec delay;
+ memset(&delay, 0, sizeof(struct itimerspec));
+ bool toSetTime = false;
+ // if tree is empty now, we remove poll and disarm timer
+ if (!curTop) {
+ mPollTask->removePoll(*this);
+ // setting the values to disarm timer
+ delay.it_value.tv_sec = 0;
+ delay.it_value.tv_nsec = 0;
+ toSetTime = true;
+ } else if (!priorTop || curTop->outRanks(*priorTop)) {
+ // do this first to avoid race condition, in case settime is called
+ // with too small an interval
+ mPollTask->addPoll(*this);
+ delay.it_value = curTop->getFutureTime();
+ toSetTime = true;
+ }
+ if (toSetTime) {
+ timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL);
+ }
+ }
+}
+
+// all the heap management is done in the MsgTask context.
+inline
+void LocTimerContainer::add(LocTimerDelegate& timer) {
+ struct MsgTimerPush : public LocMsg {
+ LocTimerContainer* mTimerContainer;
+ LocTimerDelegate* mTimer;
+ inline MsgTimerPush(LocTimerContainer& container, LocTimerDelegate& timer) :
+ LocMsg(), mTimerContainer(&container), mTimer(&timer) {}
+ inline virtual void proc() const {
+ LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer();
+ mTimerContainer->push((LocRankable&)(*mTimer));
+ mTimerContainer->updateSoonestTime(priorTop);
+ }
+ };
+
+ mMsgTask->sendMsg(new MsgTimerPush(*this, timer));
+}
+
+// all the heap management is done in the MsgTask context.
+void LocTimerContainer::remove(LocTimerDelegate& timer) {
+ struct MsgTimerRemove : public LocMsg {
+ LocTimerContainer* mTimerContainer;
+ LocTimerDelegate* mTimer;
+ inline MsgTimerRemove(LocTimerContainer& container, LocTimerDelegate& timer) :
+ LocMsg(), mTimerContainer(&container), mTimer(&timer) {}
+ inline virtual void proc() const {
+ LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer();
+
+ // update soonest timer only if mTimer is actually removed from
+ // mTimerContainer AND mTimer is not priorTop.
+ if (priorTop == ((LocHeap*)mTimerContainer)->remove((LocRankable&)*mTimer)) {
+ // if passing in NULL, we tell updateSoonestTime to update
+ // kernel with the current top timer interval.
+ mTimerContainer->updateSoonestTime(NULL);
+ }
+ // all timers are deleted here, and only here.
+ delete mTimer;
+ }
+ };
+
+ mMsgTask->sendMsg(new MsgTimerRemove(*this, timer));
+}
+
+// all the heap management is done in the MsgTask context.
+// Upon expire, we check and continuously pop the heap until
+// the top node's timeout is in the future.
+void LocTimerContainer::expire() {
+ struct MsgTimerExpire : public LocMsg {
+ LocTimerContainer* mTimerContainer;
+ inline MsgTimerExpire(LocTimerContainer& container) :
+ LocMsg(), mTimerContainer(&container) {}
+ inline virtual void proc() const {
+ struct timespec now;
+ // get time spec of now
+ clock_gettime(CLOCK_BOOTTIME, &now);
+ LocTimerDelegate timerOfNow(now);
+ // pop everything in the heap that outRanks now, i.e. has time older than now
+ // and then call expire() on that timer.
+ for (LocTimerDelegate* timer = (LocTimerDelegate*)mTimerContainer->pop();
+ NULL != timer;
+ timer = mTimerContainer->popIfOutRanks(timerOfNow)) {
+ // the timer delegate obj will be deleted before the return of this call
+ timer->expire();
+ }
+ mTimerContainer->updateSoonestTime(NULL);
+ }
+ };
+
+ struct itimerspec delay;
+ memset(&delay, 0, sizeof(struct itimerspec));
+ timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL);
+ mPollTask->removePoll(*this);
+ mMsgTask->sendMsg(new MsgTimerExpire(*this));
+}
+
+LocTimerDelegate* LocTimerContainer::popIfOutRanks(LocTimerDelegate& timer) {
+ LocTimerDelegate* poppedNode = NULL;
+ if (mTree && !timer.outRanks(*peek())) {
+ poppedNode = (LocTimerDelegate*)(pop());
+ }
+
+ return poppedNode;
+}
+
+
+/***************************LocTimerPollTask methods***************************/
+
+inline
+LocTimerPollTask::LocTimerPollTask()
+ : mFd(epoll_create(2)), mThread() {
+ // before a next call returens, a thread will be created. The run() method
+ // could already be running in parallel. Also, since each of the objs
+ // creates a thread, the container will make sure that there will be only
+ // one of such obj for our timer implementation.
+ mThread.start("LocTimerPollTask", std::make_shared<TimerRunnable>(mFd));
+}
+
+void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) {
+ struct epoll_event ev;
+ memset(&ev, 0, sizeof(ev));
+
+ ev.events = EPOLLIN;
+ ev.data.fd = timerContainer.getTimerFd();
+ // it is important that we set this context pointer with the input
+ // timer container this is how we know which container should handle
+ // which expiration.
+ ev.data.ptr = &timerContainer;
+
+ epoll_ctl(mFd, EPOLL_CTL_ADD, timerContainer.getTimerFd(), &ev);
+}
+
+inline
+void LocTimerPollTask::removePoll(LocTimerContainer& timerContainer) {
+ epoll_ctl(mFd, EPOLL_CTL_DEL, timerContainer.getTimerFd(), NULL);
+}
+
+// The polling thread context will call this method. If run() method needs to
+// be repetitvely called, it must return true from the previous call.
+bool TimerRunnable::run() {
+ struct epoll_event ev[2];
+
+ // we have max 2 descriptors to poll from
+ int fds = epoll_wait(mFd, ev, 2, -1);
+
+ // we pretty much want to continually poll until the fd is closed
+ bool rerun = (fds > 0) || (errno == EINTR);
+
+ if (fds > 0) {
+ // we may have 2 events
+ for (int i = 0; i < fds; i++) {
+ // each fd has a context pointer associated with the right timer container
+ LocTimerContainer* container = (LocTimerContainer*)(ev[i].data.ptr);
+ if (container) {
+ container->expire();
+ } else {
+ epoll_ctl(mFd, EPOLL_CTL_DEL, ev[i].data.fd, NULL);
+ }
+ }
+ }
+
+ // if rerun is true, we are requesting to be scheduled again
+ return rerun;
+}
+
+/***************************LocTimerDelegate methods***************************/
+
+inline
+LocTimerDelegate::LocTimerDelegate(LocTimer& client,
+ struct timespec& futureTime,
+ LocTimerContainer* container)
+ : mClient(&client),
+ mLock(mClient->mLock->share()),
+ mFutureTime(futureTime),
+ mContainer(container) {
+ // adding the timer into the container
+ mContainer->add(*this);
+}
+
+inline
+void LocTimerDelegate::destroyLocked() {
+ // client handle will likely be deleted soon after this
+ // method returns. Nulling this handle so that expire()
+ // won't call the callback on the dead handle any more.
+ mClient = NULL;
+
+ if (mContainer) {
+ LocTimerContainer* container = mContainer;
+ mContainer = NULL;
+ if (container) {
+ container->remove(*this);
+ }
+ } // else we do not do anything. No such *this* can be
+ // created and reached here with mContainer ever been
+ // a non NULL. So *this* must have reached the if clause
+ // once, and we want it reach there only once.
+}
+
+int LocTimerDelegate::ranks(LocRankable& rankable) {
+ int rank = -1;
+ LocTimerDelegate* timer = (LocTimerDelegate*)(&rankable);
+ if (timer) {
+ // larger time ranks lower!!!
+ // IOW, if input obj has bigger tv_sec/tv_nsec, this obj outRanks higher
+ rank = timer->mFutureTime.tv_sec - mFutureTime.tv_sec;
+ if(0 == rank)
+ {
+ //rank against tv_nsec for msec accuracy
+ rank = (int)(timer->mFutureTime.tv_nsec - mFutureTime.tv_nsec);
+ }
+ }
+ return rank;
+}
+
+inline
+void LocTimerDelegate::expire() {
+ // keeping a copy of client pointer to be safe
+ // when timeOutCallback() is called at the end of this
+ // method, *this* obj may be already deleted.
+ LocTimer* client = mClient;
+ // force a stop, which will lead to delete of this obj
+ if (client && client->stop()) {
+ // calling client callback with a pointer save on the stack
+ // only if stop() returns true, i.e. it hasn't been stopped
+ // already.
+ client->timeOutCallback();
+ }
+}
+
+
+/***************************LocTimer methods***************************/
+LocTimer::LocTimer() : mTimer(NULL), mLock(new LocSharedLock()) {
+}
+
+LocTimer::~LocTimer() {
+ stop();
+ if (mLock) {
+ mLock->drop();
+ mLock = NULL;
+ }
+}
+
+bool LocTimer::start(unsigned int timeOutInMs, bool wakeOnExpire) {
+ bool success = false;
+ mLock->lock();
+ if (!mTimer) {
+ struct timespec futureTime;
+ clock_gettime(CLOCK_BOOTTIME, &futureTime);
+ futureTime.tv_sec += timeOutInMs / 1000;
+ futureTime.tv_nsec += (timeOutInMs % 1000) * 1000000;
+ if (futureTime.tv_nsec >= 1000000000) {
+ futureTime.tv_sec += futureTime.tv_nsec / 1000000000;
+ futureTime.tv_nsec %= 1000000000;
+ }
+
+ LocTimerContainer* container;
+ container = LocTimerContainer::get(wakeOnExpire);
+ if (NULL != container) {
+ mTimer = new LocTimerDelegate(*this, futureTime, container);
+ // if mTimer is non 0, success should be 0; or vice versa
+ }
+ success = (NULL != mTimer);
+ }
+ mLock->unlock();
+ return success;
+}
+
+bool LocTimer::stop() {
+ bool success = false;
+ mLock->lock();
+ if (mTimer) {
+ LocTimerDelegate* timer = mTimer;
+ mTimer = NULL;
+ if (timer) {
+ timer->destroyLocked();
+ success = true;
+ }
+ }
+ mLock->unlock();
+ return success;
+}
+
+/***************************LocTimerWrapper methods***************************/
+//////////////////////////////////////////////////////////////////////////
+// This section below wraps for the C style APIs
+//////////////////////////////////////////////////////////////////////////
+class LocTimerWrapper : public LocTimer {
+ loc_timer_callback mCb;
+ void* mCallerData;
+ LocTimerWrapper* mMe;
+ static pthread_mutex_t mMutex;
+ inline ~LocTimerWrapper() { mCb = NULL; mMe = NULL; }
+public:
+ inline LocTimerWrapper(loc_timer_callback cb, void* callerData) :
+ mCb(cb), mCallerData(callerData), mMe(this) {
+ }
+ void destroy() {
+ pthread_mutex_lock(&mMutex);
+ if (NULL != mCb && this == mMe) {
+ delete this;
+ }
+ pthread_mutex_unlock(&mMutex);
+ }
+ virtual void timeOutCallback() {
+ loc_timer_callback cb = mCb;
+ void* callerData = mCallerData;
+ if (cb) {
+ cb(callerData, 0);
+ }
+ destroy();
+ }
+};
+
+} // namespace loc_util
+
+//////////////////////////////////////////////////////////////////////////
+// This section below wraps for the C style APIs
+//////////////////////////////////////////////////////////////////////////
+
+using loc_util::LocTimerWrapper;
+
+pthread_mutex_t LocTimerWrapper::mMutex = PTHREAD_MUTEX_INITIALIZER;
+
+void* loc_timer_start(uint64_t msec, loc_timer_callback cb_func,
+ void *caller_data, bool wake_on_expire)
+{
+ LocTimerWrapper* locTimerWrapper = NULL;
+
+ if (cb_func) {
+ locTimerWrapper = new LocTimerWrapper(cb_func, caller_data);
+
+ if (locTimerWrapper) {
+ locTimerWrapper->start(msec, wake_on_expire);
+ }
+ }
+
+ return locTimerWrapper;
+}
+
+void loc_timer_stop(void*& handle)
+{
+ if (handle) {
+ LocTimerWrapper* locTimerWrapper = (LocTimerWrapper*)(handle);
+ locTimerWrapper->destroy();
+ handle = NULL;
+ }
+}
diff --git a/gps/utils/LocTimer.h b/gps/utils/LocTimer.h
new file mode 100644
index 0000000..c883de2
--- /dev/null
+++ b/gps/utils/LocTimer.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __LOC_TIMER_CPP_H__
+#define __LOC_TIMER_CPP_H__
+
+#include <stddef.h>
+#include <loc_pla.h>
+
+namespace loc_util {
+
+// opaque class to provide service implementation.
+class LocTimerDelegate;
+class LocSharedLock;
+
+// LocTimer client must extend this class and implementthe callback.
+// start() / stop() methods are to arm / disarm timer.
+class LocTimer
+{
+ LocTimerDelegate* mTimer;
+ LocSharedLock* mLock;
+ // don't really want mLock to be manipulated by clients, yet LocTimer
+ // has to have a reference to the lock so that the delete of LocTimer
+ // and LocTimerDelegate can work together on their share resources.
+ friend class LocTimerDelegate;
+
+public:
+ LocTimer();
+ virtual ~LocTimer();
+
+ // timeOutInMs: timeout delay in ms
+ // wakeOnExpire: true if to wake up CPU (if sleeping) upon timer
+ // expiration and notify the client.
+ // false if to wait until next time CPU wakes up (if
+ // sleeping) and then notify the client.
+ // return: true on success;
+ // false on failure, e.g. timer is already running.
+ bool start(uint32_t timeOutInMs, bool wakeOnExpire);
+
+ // return: true on success;
+ // false on failure, e.g. timer is not running.
+ bool stop();
+
+ // LocTimer client Should implement this method.
+ // This method is used for timeout calling back to client. This method
+ // should be short enough (eg: send a message to your own thread).
+ virtual void timeOutCallback() = 0;
+};
+
+} // namespace loc_util
+
+#endif //__LOC_DELAY_H__
diff --git a/gps/utils/LocUnorderedSetMap.h b/gps/utils/LocUnorderedSetMap.h
new file mode 100644
index 0000000..7b25ad0
--- /dev/null
+++ b/gps/utils/LocUnorderedSetMap.h
@@ -0,0 +1,201 @@
+/* Copyright (c) 2015, 2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LOC_UNORDERDED_SETMAP_H__
+#define __LOC_UNORDERDED_SETMAP_H__
+
+#include <algorithm>
+#include <loc_pla.h>
+
+#ifdef NO_UNORDERED_SET_OR_MAP
+ #include <set>
+ #include <map>
+#else
+ #include <unordered_set>
+ #include <unordered_map>
+#endif
+
+using std::unordered_set;
+using std::unordered_map;
+
+namespace loc_util {
+
+// Trim from *fromSet* any elements that also exist in *rVals*.
+// The optional *goneVals*, if not null, will be populated with removed elements.
+template <typename T>
+inline static void trimSet(unordered_set<T>& fromSet, const unordered_set<T>& rVals,
+ unordered_set<T>* goneVals) {
+ for (auto val : rVals) {
+ if (fromSet.erase(val) > 0 && nullptr != goneVals) {
+ goneVals->insert(val);
+ }
+ }
+}
+
+// this method is destructive to the input unordered_sets.
+// the return set is the interset extracted out from the two input sets, *s1* and *s2*.
+// *s1* and *s2* will be left with the intersect removed from them.
+template <typename T>
+static unordered_set<T> removeAndReturnInterset(unordered_set<T>& s1, unordered_set<T>& s2) {
+ unordered_set<T> common = {};
+ for (auto b = s2.begin(); b != s2.end(); b++) {
+ auto a = find(s1.begin(), s1.end(), *b);
+ if (a != s1.end()) {
+ // this is a common item of both l1 and l2, remove from both
+ // but after we add to common
+ common.insert(*a);
+ s1.erase(a);
+ s2.erase(b);
+ }
+ }
+ return common;
+}
+
+template <typename KEY, typename VAL>
+class LocUnorderedSetMap {
+ unordered_map<KEY, unordered_set<VAL>> mMap;
+
+ // Trim the VALs pointed to by *iter*, with everything that also exist in *rVals*.
+ // If the set becomes empty, remove the map entry. *goneVals*, if not null, records
+ // the trimmed VALs.
+ bool trimOrRemove(typename unordered_map<KEY, unordered_set<VAL>>::iterator iter,
+ const unordered_set<VAL>& rVals, unordered_set<VAL>* goneVals) {
+ trimSet<VAL>(iter->second, rVals, goneVals);
+ bool removeEntry = (iter->second.empty());
+ if (removeEntry) {
+ mMap.erase(iter);
+ }
+ return removeEntry;
+ }
+
+public:
+ inline LocUnorderedSetMap() {}
+ inline LocUnorderedSetMap(size_t size) : LocUnorderedSetMap() {
+ mMap.get_allocator().allocate(size);
+ }
+
+ inline bool empty() { return mMap.empty(); }
+
+ // This gets the raw pointer to the VALs pointed to by *key*
+ // If the entry is not in the map, nullptr will be returned.
+ inline unordered_set<VAL>* getValSetPtr(const KEY& key) {
+ auto entry = mMap.find(key);
+ return (entry != mMap.end()) ? &(entry->second) : nullptr;
+ }
+
+ // This gets a copy of VALs pointed to by *key*
+ // If the entry is not in the map, an empty set will be returned.
+ inline unordered_set<VAL> getValSet(const KEY& key) {
+ auto entry = mMap.find(key);
+ return (entry != mMap.end()) ? entry->second : unordered_set<VAL>{};
+ }
+
+ // This gets all the KEYs from the map
+ inline unordered_set<KEY> getKeys() {
+ unordered_set<KEY> keys = {};
+ for (auto entry : mMap) {
+ keys.insert(entry.first);
+ }
+ return keys;
+ }
+
+ inline bool remove(const KEY& key) {
+ return mMap.erase(key) > 0;
+ }
+
+ // This looks into all the entries keyed by *keys*. Remove any VALs from the entries
+ // that also exist in *rVals*. If the entry is left with an empty set, the entry will
+ // be removed. The optional parameters *goneKeys* and *goneVals* will record the KEYs
+ // (or entries) and the collapsed VALs removed from the map, respectively.
+ inline void trimOrRemove(unordered_set<KEY>&& keys, const unordered_set<VAL>& rVals,
+ unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
+ trimOrRemove(keys, rVals, goneKeys, goneVals);
+ }
+
+ inline void trimOrRemove(unordered_set<KEY>& keys, const unordered_set<VAL>& rVals,
+ unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
+ for (auto key : keys) {
+ auto iter = mMap.find(key);
+ if (iter != mMap.end() && trimOrRemove(iter, rVals, goneVals) && nullptr != goneKeys) {
+ goneKeys->insert(iter->first);
+ }
+ }
+ }
+
+ // This adds all VALs from *newVals* to the map entry keyed by *key*. Or if it
+ // doesn't exist yet, add the set to the map.
+ bool add(const KEY& key, const unordered_set<VAL>& newVals) {
+ bool newEntryAdded = false;
+ if (!newVals.empty()) {
+ auto iter = mMap.find(key);
+ if (iter != mMap.end()) {
+ iter->second.insert(newVals.begin(), newVals.end());
+ } else {
+ mMap[key] = newVals;
+ newEntryAdded = true;
+ }
+ }
+ return newEntryAdded;
+ }
+
+ // This adds to each of entries in the map keyed by *keys* with the VALs in the
+ // *enwVals*. If there new entries added (new key in *keys*), *newKeys*, if not
+ // null, would be populated with those keys.
+ inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>&& newVals,
+ unordered_set<KEY>* newKeys) {
+ add(keys, newVals, newKeys);
+ }
+
+ inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>& newVals,
+ unordered_set<KEY>* newKeys) {
+ for (auto key : keys) {
+ if (add(key, newVals) && nullptr != newKeys) {
+ newKeys->insert(key);
+ }
+ }
+ }
+
+ // This puts *newVals* into the map keyed by *key*, and returns the VALs that are
+ // in effect removed from the keyed VAL set in the map entry.
+ // This call would also remove those same VALs from *newVals*.
+ inline unordered_set<VAL> update(const KEY& key, unordered_set<VAL>& newVals) {
+ unordered_set<VAL> goneVals = {};
+ if (newVals.empty()) {
+ mMap.erase(key);
+ } else {
+ auto curVals = mMap[key];
+ mMap[key] = newVals;
+ goneVals = removeAndReturnInterset(curVals, newVals);
+ }
+ return goneVals;
+ }
+};
+
+} // namespace loc_util
+
+#endif // #ifndef __LOC_UNORDERDED_SETMAP_H__
diff --git a/gps/utils/LogBuffer.cpp b/gps/utils/LogBuffer.cpp
new file mode 100644
index 0000000..c280c82
--- /dev/null
+++ b/gps/utils/LogBuffer.cpp
@@ -0,0 +1,189 @@
+/* Copyright (c) 2019 - 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "LogBuffer.h"
+#ifdef USE_GLIB
+#include <execinfo.h>
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "LocSvc_LogBuffer"
+
+namespace loc_util {
+
+LogBuffer* LogBuffer::mInstance;
+struct sigaction LogBuffer::mOriSigAction[NSIG];
+struct sigaction LogBuffer::mNewSigAction;
+mutex LogBuffer::sLock;
+
+LogBuffer* LogBuffer::getInstance() {
+ if (mInstance == nullptr) {
+ lock_guard<mutex> guard(sLock);
+ if (mInstance == nullptr) {
+ mInstance = new LogBuffer();
+ }
+ }
+ return mInstance;
+}
+
+LogBuffer::LogBuffer(): mLogList(TOTAL_LOG_LEVELS),
+ mConfigVec(TOTAL_LOG_LEVELS, ConfigsInLevel(TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC,
+ MAXIMUM_NUM_IN_LIST, 0)) {
+ loc_param_s_type log_buff_config_table[] =
+ {
+ {"E_LEVEL_TIME_DEPTH", &mConfigVec[0].mTimeDepthThres, NULL, 'n'},
+ {"E_LEVEL_MAX_CAPACITY", &mConfigVec[0].mMaxNumThres, NULL, 'n'},
+ {"W_LEVEL_TIME_DEPTH", &mConfigVec[1].mTimeDepthThres, NULL, 'n'},
+ {"W_LEVEL_MAX_CAPACITY", &mConfigVec[1].mMaxNumThres, NULL, 'n'},
+ {"I_LEVEL_TIME_DEPTH", &mConfigVec[2].mTimeDepthThres, NULL, 'n'},
+ {"I_LEVEL_MAX_CAPACITY", &mConfigVec[2].mMaxNumThres, NULL, 'n'},
+ {"D_LEVEL_TIME_DEPTH", &mConfigVec[3].mTimeDepthThres, NULL, 'n'},
+ {"D_LEVEL_MAX_CAPACITY", &mConfigVec[3].mMaxNumThres, NULL, 'n'},
+ {"V_LEVEL_TIME_DEPTH", &mConfigVec[4].mTimeDepthThres, NULL, 'n'},
+ {"V_LEVEL_MAX_CAPACITY", &mConfigVec[4].mMaxNumThres, NULL, 'n'},
+ };
+ loc_read_conf(LOC_PATH_GPS_CONF_STR, log_buff_config_table,
+ sizeof(log_buff_config_table)/sizeof(log_buff_config_table[0]));
+ registerSignalHandler();
+}
+
+void LogBuffer::append(string& data, int level, uint64_t timestamp) {
+ lock_guard<mutex> guard(mLock);
+ pair<uint64_t, string> item(timestamp, data);
+ mLogList.append(item, level);
+ mConfigVec[level].mCurrentSize++;
+
+ while ((timestamp - mLogList.front(level).first) > mConfigVec[level].mTimeDepthThres ||
+ mConfigVec[level].mCurrentSize > mConfigVec[level].mMaxNumThres) {
+ mLogList.pop(level);
+ mConfigVec[level].mCurrentSize--;
+ }
+}
+
+//Dump the log buffer of specific level, level = -1 to dump all the levels in log buffer.
+void LogBuffer::dump(std::function<void(stringstream&)> log, int level) {
+ lock_guard<mutex> guard(mLock);
+ list<pair<pair<uint64_t, string>, int>> li;
+ if (-1 == level) {
+ li = mLogList.dump();
+ } else {
+ li = mLogList.dump(level);
+ }
+ ALOGE("Begining of dump, buffer size: %d", (int)li.size());
+ stringstream ln;
+ ln << "dump log buffer, level[" << level << "]" << ", buffer size: " << li.size() << endl;
+ log(ln);
+ for_each (li.begin(), li.end(), [&, this](const pair<pair<uint64_t, string>, int> &item){
+ stringstream line;
+ line << "["<<item.first.first << "] ";
+ line << "Level " << mLevelMap[item.second] << ": ";
+ line << item.first.second << endl;
+ if (log != nullptr) {
+ log(line);
+ }
+ });
+ ALOGE("End of dump");
+}
+
+void LogBuffer::dumpToAdbLogcat() {
+ dump([](stringstream& line){
+ ALOGE("%s", line.str().c_str());
+ });
+}
+
+void LogBuffer::dumpToLogFile(string filePath) {
+ ALOGE("Dump GPS log buffer to file: %s", filePath.c_str());
+ fstream s;
+ s.open(filePath, std::fstream::out | std::fstream::app);
+ dump([&s](stringstream& line){
+ s << line.str();
+ });
+ s.close();
+}
+
+void LogBuffer::flush() {
+ mLogList.flush();
+}
+
+void LogBuffer::registerSignalHandler() {
+ ALOGE("Singal handler registered");
+ mNewSigAction.sa_sigaction = &LogBuffer::signalHandler;
+ mNewSigAction.sa_flags = SA_SIGINFO | SA_RESTART;
+ sigemptyset(&mNewSigAction.sa_mask);
+
+ sigaction(SIGINT, &mNewSigAction, &mOriSigAction[SIGINT]);
+ sigaction(SIGKILL, &mNewSigAction, &mOriSigAction[SIGKILL]);
+ sigaction(SIGSEGV, &mNewSigAction, &mOriSigAction[SIGSEGV]);
+ sigaction(SIGABRT, &mNewSigAction, &mOriSigAction[SIGABRT]);
+ sigaction(SIGTRAP, &mNewSigAction, &mOriSigAction[SIGTRAP]);
+ sigaction(SIGUSR1, &mNewSigAction, &mOriSigAction[SIGUSR1]);
+}
+
+void LogBuffer::signalHandler(const int code, siginfo_t *const si, void *const sc) {
+ ALOGE("[Gnss Log buffer]Singal handler, signal ID: %d", code);
+
+#ifdef USE_GLIB
+ int nptrs;
+ void *buffer[100];
+ char **strings;
+
+ nptrs = backtrace(buffer, sizeof(buffer)/sizeof(*buffer));
+ strings = backtrace_symbols(buffer, nptrs);
+ if (strings != NULL) {
+ timespec tv;
+ clock_gettime(CLOCK_BOOTTIME, &tv);
+ uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
+ for (int i = 0; i < nptrs; i++) {
+ string s(strings[i]);
+ mInstance->append(s, 0, elapsedTime);
+ }
+ }
+#endif
+ //Dump the log buffer to adb logcat
+ mInstance->dumpToAdbLogcat();
+
+ //Dump the log buffer to file
+ time_t now = time(NULL);
+ struct tm *curr_time = localtime(&now);
+ char path[50];
+ snprintf(path, 50, LOG_BUFFER_FILE_PATH "gpslog_%d%d%d-%d%d%d.log",
+ (1900 + curr_time->tm_year), ( 1 + curr_time->tm_mon), curr_time->tm_mday,
+ curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec);
+
+ mInstance->dumpToLogFile(path);
+
+ //Process won't be terminated if SIGUSR1 is recieved
+ if (code != SIGUSR1) {
+ mOriSigAction[code].sa_sigaction(code, si, sc);
+ }
+}
+
+}
diff --git a/gps/utils/LogBuffer.h b/gps/utils/LogBuffer.h
new file mode 100644
index 0000000..8d90439
--- /dev/null
+++ b/gps/utils/LogBuffer.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOG_BUFFER_H
+#define LOG_BUFFER_H
+
+#include "SkipList.h"
+#include "log_util.h"
+#include <loc_cfg.h>
+#include <loc_pla.h>
+#include <string>
+#include <sstream>
+#include <ostream>
+#include <fstream>
+#include <time.h>
+#include <mutex>
+#include <signal.h>
+#include <thread>
+#include <functional>
+
+//default error level time depth threshold,
+#define TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC 60
+//default maximum log buffer size
+#define MAXIMUM_NUM_IN_LIST 50
+//file path of dumped log buffer
+#define LOG_BUFFER_FILE_PATH "/data/vendor/location/"
+
+namespace loc_util {
+
+class ConfigsInLevel{
+public:
+ uint32_t mTimeDepthThres;
+ uint32_t mMaxNumThres;
+ int mCurrentSize;
+
+ ConfigsInLevel(uint32_t time, int num, int size):
+ mTimeDepthThres(time), mMaxNumThres(num), mCurrentSize(size) {}
+};
+
+class LogBuffer {
+private:
+ static LogBuffer* mInstance;
+ static struct sigaction mOriSigAction[NSIG];
+ static struct sigaction mNewSigAction;
+ static mutex sLock;
+
+ SkipList<pair<uint64_t, string>> mLogList;
+ vector<ConfigsInLevel> mConfigVec;
+ mutex mLock;
+
+ const vector<string> mLevelMap {"E", "W", "I", "D", "V"};
+
+public:
+ static LogBuffer* getInstance();
+ void append(string& data, int level, uint64_t timestamp);
+ void dump(std::function<void(stringstream&)> log, int level = -1);
+ void dumpToAdbLogcat();
+ void dumpToLogFile(string filePath);
+ void flush();
+private:
+ LogBuffer();
+ void registerSignalHandler();
+ static void signalHandler(const int code, siginfo_t *const si, void *const sc);
+
+};
+
+}
+
+#endif
diff --git a/gps/utils/Makefile.am b/gps/utils/Makefile.am
new file mode 100644
index 0000000..ada504c
--- /dev/null
+++ b/gps/utils/Makefile.am
@@ -0,0 +1,75 @@
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS = -Wundef \
+ -MD \
+ -Wno-trigraphs \
+ -g -O0 \
+ -fno-inline \
+ -fno-short-enums \
+ -fpic \
+ -I./ \
+ -std=c++14 \
+ $(LOCPLA_CFLAGS)
+
+libgps_utils_la_h_sources = \
+ msg_q.h \
+ linked_list.h \
+ loc_cfg.h \
+ loc_log.h \
+ loc_target.h \
+ loc_timer.h \
+ MsgTask.h \
+ LocHeap.h \
+ LocThread.h \
+ LocTimer.h \
+ LocIpc.h \
+ SkipList.h\
+ loc_misc_utils.h \
+ loc_nmea.h \
+ gps_extended_c.h \
+ gps_extended.h \
+ loc_gps.h \
+ log_util.h \
+ LocSharedLock.h \
+ LocUnorderedSetMap.h\
+ LocLoggerBase.h
+
+libgps_utils_la_c_sources = \
+ linked_list.c \
+ msg_q.c \
+ loc_cfg.cpp \
+ loc_log.cpp \
+ loc_target.cpp \
+ LocHeap.cpp \
+ LocTimer.cpp \
+ LocThread.cpp \
+ LocIpc.cpp \
+ LogBuffer.cpp \
+ MsgTask.cpp \
+ loc_misc_utils.cpp \
+ loc_nmea.cpp
+
+library_includedir = $(pkgincludedir)
+
+library_include_HEADERS = $(libgps_utils_la_h_sources)
+
+libgps_utils_la_SOURCES = $(libgps_utils_la_c_sources)
+
+if USE_GLIB
+libgps_utils_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
+libgps_utils_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
+libgps_utils_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
+else
+libgps_utils_la_CFLAGS = $(AM_CFLAGS)
+libgps_utils_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
+libgps_utils_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
+endif
+
+libgps_utils_la_LIBADD = $(CUTILS_LIBS) -ldl
+
+#Create and Install libraries
+lib_LTLIBRARIES = libgps_utils.la
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gps-utils.pc
+EXTRA_DIST = $(pkgconfig_DATA)
diff --git a/gps/utils/MsgTask.cpp b/gps/utils/MsgTask.cpp
new file mode 100644
index 0000000..6ef689a
--- /dev/null
+++ b/gps/utils/MsgTask.cpp
@@ -0,0 +1,120 @@
+/* Copyright (c) 2011-2013, 2015, 2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_MsgTask"
+
+#include <unistd.h>
+#include <MsgTask.h>
+#include <msg_q.h>
+#include <log_util.h>
+#include <loc_log.h>
+#include <loc_pla.h>
+
+namespace loc_util {
+
+class MTRunnable : public LocRunnable {
+ const void* mQ;
+public:
+ inline MTRunnable(const void* q) : mQ(q) {}
+ virtual ~MTRunnable();
+ // Overrides of LocRunnable methods
+ // This method will be repeated called until it returns false; or
+ // until thread is stopped.
+ virtual bool run() override;
+
+ // The method to be run before thread loop (conditionally repeatedly)
+ // calls run()
+ virtual void prerun() override;
+
+ // to interrupt the run() method and come out of that
+ virtual void interrupt() override;
+};
+
+static void LocMsgDestroy(void* msg) {
+ delete (LocMsg*)msg;
+}
+
+MsgTask::MsgTask(const char* threadName) :
+ mQ(msg_q_init2()), mThread() {
+ mThread.start(threadName, std::make_shared<MTRunnable>(mQ));
+}
+
+void MsgTask::sendMsg(const LocMsg* msg) const {
+ if (msg && this) {
+ msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy);
+ } else {
+ LOC_LOGE("%s: msg is %p and this is %p",
+ __func__, msg, this);
+ }
+}
+
+void MsgTask::sendMsg(const std::function<void()> runnable) const {
+ struct RunMsg : public LocMsg {
+ const std::function<void()> mRunnable;
+ public:
+ inline RunMsg(const std::function<void()> runnable) : mRunnable(runnable) {}
+ ~RunMsg() = default;
+ inline virtual void proc() const override { mRunnable(); }
+ };
+ sendMsg(new RunMsg(runnable));
+}
+
+void MTRunnable::interrupt() {
+ msg_q_unblock((void*)mQ);
+}
+
+void MTRunnable::prerun() {
+ // make sure we do not run in background scheduling group
+ set_sched_policy(gettid(), SP_FOREGROUND);
+}
+
+bool MTRunnable::run() {
+ LocMsg* msg;
+ msq_q_err_type result = msg_q_rcv((void*)mQ, (void **)&msg);
+ if (eMSG_Q_SUCCESS != result) {
+ LOC_LOGE("%s:%d] fail receiving msg: %s\n", __func__, __LINE__,
+ loc_get_msg_q_status(result));
+ return false;
+ }
+
+ msg->log();
+ // there is where each individual msg handling is invoked
+ msg->proc();
+
+ delete msg;
+
+ return true;
+}
+
+MTRunnable::~MTRunnable() {
+ msg_q_flush((void*)mQ);
+ msg_q_destroy((void**)&mQ);
+}
+
+} // namespace loc_util
diff --git a/gps/utils/MsgTask.h b/gps/utils/MsgTask.h
new file mode 100644
index 0000000..a8cce9e
--- /dev/null
+++ b/gps/utils/MsgTask.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2011-2013, 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __MSG_TASK__
+#define __MSG_TASK__
+
+#include <functional>
+#include <LocThread.h>
+
+namespace loc_util {
+
+struct LocMsg {
+ inline LocMsg() {}
+ inline virtual ~LocMsg() {}
+ virtual void proc() const = 0;
+ inline virtual void log() const {}
+};
+
+class MsgTask {
+ const void* mQ;
+ LocThread mThread;
+public:
+ ~MsgTask() = default;
+ MsgTask(const char* threadName = NULL);
+ void sendMsg(const LocMsg* msg) const;
+ void sendMsg(const std::function<void()> runnable) const;
+};
+
+} //
+
+#endif //__MSG_TASK__
diff --git a/gps/utils/SkipList.h b/gps/utils/SkipList.h
new file mode 100644
index 0000000..afaa1a6
--- /dev/null
+++ b/gps/utils/SkipList.h
@@ -0,0 +1,158 @@
+/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_SKIP_LIST_H
+#define LOC_SKIP_LIST_H
+
+#include <stdlib.h>
+#include <list>
+#include <vector>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+namespace loc_util {
+
+template <typename T,
+ template<typename elem, typename Allocator = std::allocator<elem>> class container = list>
+class SkipNode {
+public:
+ typedef typename container<SkipNode<T, container>>::iterator NodeIterator;
+
+ int mLevel;
+ T mData;
+ NodeIterator mNextInLevel;
+
+ SkipNode(int level, T& data): mLevel(level), mData(data) {}
+};
+
+template <typename T>
+class SkipList {
+ using NodeIterator = typename SkipNode<T>::NodeIterator;
+private:
+ list<SkipNode<T>> mMainList;
+ vector<NodeIterator> mHeadVec;
+ vector<NodeIterator> mTailVec;
+public:
+ SkipList(int totalLevels);
+ void append(T& data, int level);
+ void pop(int level);
+ void pop();
+ T front(int level);
+ int size();
+ void flush();
+ list<pair<T, int>> dump();
+ list<pair<T, int>> dump(int level);
+};
+
+template <typename T>
+SkipList<T>::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()),
+ mTailVec(totalLevels, mMainList.end()) {}
+
+template <typename T>
+void SkipList<T>::append(T& data, int level) {
+ if ( level < 0 || level >= mHeadVec.size()) {
+ return;
+ }
+
+ SkipNode<T> node(level, data);
+ node.mNextInLevel = mMainList.end();
+ mMainList.push_back(node);
+ auto iter = --mMainList.end();
+ if (mHeadVec[level] == mMainList.end()) {
+ mHeadVec[level] = iter;
+ } else {
+ (*mTailVec[level]).mNextInLevel = iter;
+ }
+ mTailVec[level] = iter;
+}
+
+template <typename T>
+void SkipList<T>::pop(int level) {
+ if (mHeadVec[level] == mMainList.end()) {
+ return;
+ }
+
+ if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) {
+ mTailVec[level] = mMainList.end();
+ }
+
+ auto tmp_iter = (*mHeadVec[level]).mNextInLevel;
+ mMainList.erase(mHeadVec[level]);
+ mHeadVec[level] = tmp_iter;
+}
+
+template <typename T>
+void SkipList<T>::pop() {
+ pop(mMainList.front().mLevel);
+}
+
+template <typename T>
+T SkipList<T>::front(int level) {
+ return (*mHeadVec[level]).mData;
+}
+
+template <typename T>
+int SkipList<T>::size() {
+ return mMainList.size();
+}
+
+template <typename T>
+void SkipList<T>::flush() {
+ mMainList.clear();
+ for (int i = 0; i < mHeadVec.size(); i++) {
+ mHeadVec[i] = mMainList.end();
+ mTailVec[i] = mMainList.end();
+ }
+}
+
+template <typename T>
+list<pair<T, int>> SkipList<T>::dump() {
+ list<pair<T, int>> li;
+ for_each(mMainList.begin(), mMainList.end(), [&](SkipNode<T> &item) {
+ li.push_back(make_pair(item.mData, item.mLevel));
+ });
+ return li;
+}
+
+template <typename T>
+list<pair<T, int>> SkipList<T>::dump(int level) {
+ list<pair<T, int>> li;
+ auto head = mHeadVec[level];
+ while (head != mMainList.end()) {
+ li.push_back(make_pair((*head).mData, (*head).mLevel));
+ head = (*head).mNextInLevel;
+ }
+ return li;
+}
+
+}
+
+#endif
diff --git a/gps/utils/configure.ac b/gps/utils/configure.ac
new file mode 100644
index 0000000..2a04f45
--- /dev/null
+++ b/gps/utils/configure.ac
@@ -0,0 +1,92 @@
+# configure.ac -- Autoconf script for gps gps-utils
+#
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the gps gps-utils package version 1.0.0
+AC_INIT([gps-utils],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# Verifies the --srcdir is correct by checking for the path
+AC_CONFIG_SRCDIR([Makefile.am])
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+AC_ARG_WITH([external_ap],
+ AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
+ [Using External Application Processor]),
+ [],
+ with_external_ap=no)
+
+if test "x$with_external_ap" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
+else
+ # Checks for libraries.
+ PKG_CHECK_MODULES([CUTILS], [libcutils])
+ AC_SUBST([CUTILS_CFLAGS])
+ AC_SUBST([CUTILS_LIBS])
+fi
+
+AC_ARG_WITH([core_includes],
+ AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+ [Specify the location of the core headers]),
+ [core_incdir=$withval],
+ with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+ CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH([locpla_includes],
+ AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
+ [specify the path to locpla-includes in loc-pla_git.bb]),
+ [locpla_incdir=$withval],
+ with_locpla_includes=no)
+
+if test "x$with_locpla_includes" != "xno"; then
+ AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
+fi
+
+AC_SUBST([CPPFLAGS])
+
+AC_ARG_WITH([glib],
+ AC_HELP_STRING([--with-glib],
+ [enable glib, building HLOS systems which use glib]))
+
+if (test "x${with_glib}" = "xyes"); then
+ AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GThread >= 2.16 is required))
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.16 is required))
+ GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
+ GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+fi
+
+AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
+
+AC_CONFIG_FILES([ \
+ Makefile \
+ gps-utils.pc
+ ])
+
+AC_OUTPUT
diff --git a/gps/utils/gps-utils.pc.in b/gps/utils/gps-utils.pc.in
new file mode 100644
index 0000000..a988731
--- /dev/null
+++ b/gps/utils/gps-utils.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gps-utils
+Description: QTI GPS Location utils
+Version: @VERSION
+Libs: -L${libdir} -lgps_utils
+Cflags: -I${includedir}/gps-utils
diff --git a/gps/utils/gps_extended.h b/gps/utils/gps_extended.h
new file mode 100644
index 0000000..2455629
--- /dev/null
+++ b/gps/utils/gps_extended.h
@@ -0,0 +1,114 @@
+/* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GPS_EXTENDED_H
+#define GPS_EXTENDED_H
+
+/**
+ * @file
+ * @brief C++ declarations for GPS types
+ */
+
+#include <gps_extended_c.h>
+#if defined(USE_GLIB) || defined(OFF_TARGET)
+#include <string.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+struct LocPosMode
+{
+ LocPositionMode mode;
+ LocGpsPositionRecurrence recurrence;
+ uint32_t min_interval;
+ uint32_t preferred_accuracy;
+ uint32_t preferred_time;
+ bool share_position;
+ char credentials[14];
+ char provider[8];
+ GnssPowerMode powerMode;
+ uint32_t timeBetweenMeasurements;
+ LocPosMode(LocPositionMode m, LocGpsPositionRecurrence recr,
+ uint32_t gap, uint32_t accu, uint32_t time,
+ bool sp, const char* cred, const char* prov,
+ GnssPowerMode pMode = GNSS_POWER_MODE_INVALID,
+ uint32_t tbm = 0) :
+ mode(m), recurrence(recr),
+ min_interval(gap < GPS_MIN_POSSIBLE_FIX_INTERVAL_MS ?
+ GPS_MIN_POSSIBLE_FIX_INTERVAL_MS : gap),
+ preferred_accuracy(accu), preferred_time(time),
+ share_position(sp), powerMode(pMode),
+ timeBetweenMeasurements(tbm) {
+ memset(credentials, 0, sizeof(credentials));
+ memset(provider, 0, sizeof(provider));
+ if (NULL != cred) {
+ memcpy(credentials, cred, sizeof(credentials)-1);
+ }
+ if (NULL != prov) {
+ memcpy(provider, prov, sizeof(provider)-1);
+ }
+ }
+
+ inline LocPosMode() :
+ mode(LOC_POSITION_MODE_MS_BASED),
+ recurrence(LOC_GPS_POSITION_RECURRENCE_PERIODIC),
+ min_interval(GPS_DEFAULT_FIX_INTERVAL_MS),
+ preferred_accuracy(50), preferred_time(120000),
+ share_position(true), powerMode(GNSS_POWER_MODE_INVALID),
+ timeBetweenMeasurements(GPS_DEFAULT_FIX_INTERVAL_MS) {
+ memset(credentials, 0, sizeof(credentials));
+ memset(provider, 0, sizeof(provider));
+ }
+
+ inline bool equals(const LocPosMode &anotherMode) const
+ {
+ return anotherMode.mode == mode &&
+ anotherMode.recurrence == recurrence &&
+ anotherMode.min_interval == min_interval &&
+ anotherMode.preferred_accuracy == preferred_accuracy &&
+ anotherMode.preferred_time == preferred_time &&
+ anotherMode.powerMode == powerMode &&
+ anotherMode.timeBetweenMeasurements == timeBetweenMeasurements &&
+ !strncmp(anotherMode.credentials, credentials, sizeof(credentials)-1) &&
+ !strncmp(anotherMode.provider, provider, sizeof(provider)-1);
+ }
+
+ void logv() const;
+};
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* GPS_EXTENDED_H */
+
diff --git a/gps/utils/gps_extended_c.h b/gps/utils/gps_extended_c.h
new file mode 100644
index 0000000..f368975
--- /dev/null
+++ b/gps/utils/gps_extended_c.h
@@ -0,0 +1,2429 @@
+/* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GPS_EXTENDED_C_H
+#define GPS_EXTENDED_C_H
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <loc_gps.h>
+#include <LocationAPI.h>
+
+struct timespec32_t {
+ uint32_t tv_sec; /* seconds */
+ uint32_t tv_nsec; /* and nanoseconds */
+};
+
+
+/**
+ * @file
+ * @brief C++ declarations for GPS types
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Location has valid source information. */
+#define LOCATION_HAS_SOURCE_INFO 0x0020
+/** LocGpsLocation has valid "is indoor?" flag */
+#define LOC_GPS_LOCATION_HAS_IS_INDOOR 0x0040
+/** LocGpsLocation has valid floor number */
+#define LOC_GPS_LOCATION_HAS_FLOOR_NUMBER 0x0080
+/** LocGpsLocation has valid map URL*/
+#define LOC_GPS_LOCATION_HAS_MAP_URL 0x0100
+/** LocGpsLocation has valid map index */
+#define LOC_GPS_LOCATION_HAS_MAP_INDEX 0x0200
+
+#define GNSS_INVALID_JAMMER_IND 0x7FFFFFFF
+
+/** Sizes for indoor fields */
+#define GPS_LOCATION_MAP_URL_SIZE 400
+#define GPS_LOCATION_MAP_INDEX_SIZE 16
+
+/** Position source is ULP */
+#define ULP_LOCATION_IS_FROM_HYBRID 0x0001
+/** Position source is GNSS only */
+#define ULP_LOCATION_IS_FROM_GNSS 0x0002
+/** Position is from a Geofence Breach Event */
+#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0004
+/** Position is from Hardware FLP */
+#define ULP_LOCATION_IS_FROM_HW_FLP 0x0008
+/** Position is from NLP */
+#define ULP_LOCATION_IS_FROM_NLP 0x0010
+/** Position is from external DR solution*/
+#define ULP_LOCATION_IS_FROM_EXT_DR 0X0020
+/** Raw GNSS position fixes */
+#define ULP_LOCATION_IS_FROM_GNSS_RAW 0X0040
+
+typedef uint32_t LocSvInfoSource;
+/** SVinfo source is GNSS/DR */
+#define ULP_SVINFO_IS_FROM_GNSS ((LocSvInfoSource)0x0001)
+/** Raw SVinfo from GNSS */
+#define ULP_SVINFO_IS_FROM_DR ((LocSvInfoSource)0x0002)
+
+#define ULP_MIN_INTERVAL_INVALID 0xffffffff
+#define ULP_MAX_NMEA_STRING_SIZE 201
+
+/*Emergency SUPL*/
+#define LOC_GPS_NI_TYPE_EMERGENCY_SUPL 4
+
+#define LOC_AGPS_CERTIFICATE_MAX_LENGTH 2000
+#define LOC_AGPS_CERTIFICATE_MAX_SLOTS 10
+
+/* TBM Threshold for tracking in background power mode : in millis */
+#define TRACKING_TBM_THRESHOLD_MILLIS 480000
+
+/** Maximum number of satellites in an ephemeris report. */
+#define GNSS_EPHEMERIS_LIST_MAX_SIZE_V02 32
+
+typedef uint32_t LocPosTechMask;
+#define LOC_POS_TECH_MASK_DEFAULT ((LocPosTechMask)0x00000000)
+#define LOC_POS_TECH_MASK_SATELLITE ((LocPosTechMask)0x00000001)
+#define LOC_POS_TECH_MASK_CELLID ((LocPosTechMask)0x00000002)
+#define LOC_POS_TECH_MASK_WIFI ((LocPosTechMask)0x00000004)
+#define LOC_POS_TECH_MASK_SENSORS ((LocPosTechMask)0x00000008)
+#define LOC_POS_TECH_MASK_REFERENCE_LOCATION ((LocPosTechMask)0x00000010)
+#define LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION ((LocPosTechMask)0x00000020)
+#define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040)
+#define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080)
+#define LOC_POS_TECH_MASK_PPE ((LocPosTechMask)0x00000100)
+#define LOC_POS_TECH_MASK_VEH ((LocPosTechMask)0x00000200)
+#define LOC_POS_TECH_MASK_VIS ((LocPosTechMask)0x00000400)
+
+
+enum loc_registration_mask_status {
+ LOC_REGISTRATION_MASK_ENABLED,
+ LOC_REGISTRATION_MASK_DISABLED,
+ LOC_REGISTRATION_MASK_SET
+};
+
+typedef enum {
+ LOC_SUPPORTED_FEATURE_ODCPI_2_V02 = 0, /**< Support ODCPI version 2 feature */
+ LOC_SUPPORTED_FEATURE_WIFI_AP_DATA_INJECT_2_V02, /**< Support Wifi AP data inject version 2 feature */
+ LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02, /**< Support debug NMEA feature */
+ LOC_SUPPORTED_FEATURE_GNSS_ONLY_POSITION_REPORT, /**< Support GNSS Only position reports */
+ LOC_SUPPORTED_FEATURE_FDCL, /**< Support FDCL */
+ LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02, /**< Support constellation enablement */
+ LOC_SUPPORTED_FEATURE_AGPM_V02, /**< Support AGPM feature */
+ LOC_SUPPORTED_FEATURE_XTRA_INTEGRITY, /**< Support XTRA integrity */
+ LOC_SUPPORTED_FEATURE_FDCL_2, /**< Support FDCL V2 */
+ LOC_SUPPORTED_FEATURE_LOCATION_PRIVACY, /**< Support location privacy */
+ LOC_SUPPORTED_FEATURE_NAVIC, /**< Support NAVIC constellation */
+ LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION, /**< Support measurements correction */
+ LOC_SUPPORTED_FEATURE_ROBUST_LOCATION, /**< Support Robust Location feature */
+ LOC_SUPPORTED_FEATURE_EDGNSS /**< Support precise location dgnss */
+} loc_supported_feature_enum;
+
+typedef struct {
+ /** set to sizeof(UlpLocation) */
+ uint32_t size;
+ LocGpsLocation gpsLocation;
+ /* Provider indicator for HYBRID or GPS */
+ uint16_t position_source;
+ LocPosTechMask tech_mask;
+ bool unpropagatedPosition;
+} UlpLocation;
+
+typedef struct {
+ /** set to sizeof(UlpNmea) */
+ uint32_t size;
+ char nmea_str[ULP_MAX_NMEA_STRING_SIZE];
+ unsigned int len;
+} UlpNmea;
+
+
+/** AGPS type */
+typedef int8_t AGpsExtType;
+#define LOC_AGPS_TYPE_INVALID -1
+#define LOC_AGPS_TYPE_ANY 0
+#define LOC_AGPS_TYPE_SUPL 1
+#define LOC_AGPS_TYPE_C2K 2
+#define LOC_AGPS_TYPE_WWAN_ANY 3
+#define LOC_AGPS_TYPE_WIFI 4
+#define LOC_AGPS_TYPE_SUPL_ES 5
+
+/** SSID length */
+#define SSID_BUF_SIZE (32+1)
+
+typedef int16_t AGpsBearerType;
+#define AGPS_APN_BEARER_INVALID 0
+#define AGPS_APN_BEARER_IPV4 1
+#define AGPS_APN_BEARER_IPV6 2
+#define AGPS_APN_BEARER_IPV4V6 3
+
+typedef uint32_t LocApnTypeMask;
+/**< Denotes APN type for Default/Internet traffic */
+#define LOC_APN_TYPE_MASK_DEFAULT ((LocApnTypeMask)0x00000001)
+/**< Denotes APN type for IP Multimedia Subsystem */
+#define LOC_APN_TYPE_MASK_IMS ((LocApnTypeMask)0x00000002)
+/**< Denotes APN type for Multimedia Messaging Service */
+#define LOC_APN_TYPE_MASK_MMS ((LocApnTypeMask)0x00000004)
+/**< Denotes APN type for Dial Up Network */
+#define LOC_APN_TYPE_MASK_DUN ((LocApnTypeMask)0x00000008)
+/**< Denotes APN type for Secure User Plane Location */
+#define LOC_APN_TYPE_MASK_SUPL ((LocApnTypeMask)0x00000010)
+/**< Denotes APN type for High Priority Mobile Data */
+#define LOC_APN_TYPE_MASK_HIPRI ((LocApnTypeMask)0x00000020)
+/**< Denotes APN type for over the air administration */
+#define LOC_APN_TYPE_MASK_FOTA ((LocApnTypeMask)0x00000040)
+/**< Denotes APN type for Carrier Branded Services */
+#define LOC_APN_TYPE_MASK_CBS ((LocApnTypeMask)0x00000080)
+/**< Denotes APN type for Initial Attach */
+#define LOC_APN_TYPE_MASK_IA ((LocApnTypeMask)0x00000100)
+/**< Denotes APN type for emergency */
+#define LOC_APN_TYPE_MASK_EMERGENCY ((LocApnTypeMask)0x00000200)
+
+typedef uint32_t AGpsTypeMask;
+#define AGPS_ATL_TYPE_SUPL ((AGpsTypeMask)0x00000001)
+#define AGPS_ATL_TYPE_SUPL_ES ((AGpsTypeMask)0x00000002)
+#define AGPS_ATL_TYPE_WWAN ((AGpsTypeMask)0x00000004)
+
+typedef struct {
+ void* statusV4Cb;
+ AGpsTypeMask atlType;
+} AgpsCbInfo;
+
+typedef struct {
+ void* visibilityControlCb;
+ void* isInEmergencySession;
+} NfwCbInfo;
+
+/** GPS extended callback structure. */
+typedef struct {
+ /** set to sizeof(LocGpsCallbacks) */
+ uint32_t size;
+ loc_gps_set_capabilities set_capabilities_cb;
+ loc_gps_acquire_wakelock acquire_wakelock_cb;
+ loc_gps_release_wakelock release_wakelock_cb;
+ loc_gps_create_thread create_thread_cb;
+ loc_gps_request_utc_time request_utc_time_cb;
+} GpsExtCallbacks;
+
+/** Callback to report the xtra server url to the client.
+ * The client should use this url when downloading xtra unless overwritten
+ * in the gps.conf file
+ */
+typedef void (* report_xtra_server)(const char*, const char*, const char*);
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+ loc_gps_xtra_download_request download_request_cb;
+ loc_gps_create_thread create_thread_cb;
+ report_xtra_server report_xtra_server_cb;
+} GpsXtraExtCallbacks;
+
+/** Represents the status of AGPS. */
+typedef struct {
+ /** set to sizeof(AGpsExtStatus) */
+ uint32_t size;
+
+ AGpsExtType type;
+ LocAGpsStatusValue status;
+ uint32_t ipv4_addr;
+ struct sockaddr_storage addr;
+ char ssid[SSID_BUF_SIZE];
+ char password[SSID_BUF_SIZE];
+} AGpsExtStatus;
+
+/** Callback with AGPS status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* agps_status_extended)(AGpsExtStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+ agps_status_extended status_cb;
+ loc_gps_create_thread create_thread_cb;
+} AGpsExtCallbacks;
+
+
+typedef void (*loc_ni_notify_callback)(LocGpsNiNotification *notification, bool esEnalbed);
+/** GPS NI callback structure. */
+typedef struct
+{
+ /**
+ * Sends the notification request from HAL to GPSLocationProvider.
+ */
+ loc_ni_notify_callback notify_cb;
+} GpsNiExtCallbacks;
+
+typedef enum loc_server_type {
+ LOC_AGPS_CDMA_PDE_SERVER,
+ LOC_AGPS_CUSTOM_PDE_SERVER,
+ LOC_AGPS_MPC_SERVER,
+ LOC_AGPS_SUPL_SERVER,
+ LOC_AGPS_MO_SUPL_SERVER
+} LocServerType;
+
+typedef enum loc_position_mode_type {
+ LOC_POSITION_MODE_INVALID = -1,
+ LOC_POSITION_MODE_STANDALONE = 0,
+ LOC_POSITION_MODE_MS_BASED,
+ LOC_POSITION_MODE_MS_ASSISTED,
+ LOC_POSITION_MODE_RESERVED_1,
+ LOC_POSITION_MODE_RESERVED_2,
+ LOC_POSITION_MODE_RESERVED_3,
+ LOC_POSITION_MODE_RESERVED_4,
+ LOC_POSITION_MODE_RESERVED_5
+
+} LocPositionMode;
+
+/**
+ * @brief Minimum allowed value for fix interval.
+ *
+ * This value is a sanity limit in GPS framework. The hardware has own internal
+ * limits that may not match this value
+ *
+ * @sa GPS_DEFAULT_FIX_INTERVAL_MS
+ */
+
+#define GPS_MIN_POSSIBLE_FIX_INTERVAL_MS 100
+/**
+ * @brief Default value for fix interval.
+ *
+ * This value is used by default whenever appropriate.
+ *
+ * @sa GPS_MIN_POSSIBLE_FIX_INTERVAL_MS
+ */
+#define GPS_DEFAULT_FIX_INTERVAL_MS 1000
+
+/** Flags to indicate which values are valid in a GpsLocationExtended. */
+typedef uint64_t GpsLocationExtendedFlags;
+/** GpsLocationExtended has valid pdop, hdop, vdop. */
+#define GPS_LOCATION_EXTENDED_HAS_DOP 0x0001
+/** GpsLocationExtended has valid altitude mean sea level. */
+#define GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL 0x0002
+/** UlpLocation has valid magnetic deviation. */
+#define GPS_LOCATION_EXTENDED_HAS_MAG_DEV 0x0004
+/** UlpLocation has valid mode indicator. */
+#define GPS_LOCATION_EXTENDED_HAS_MODE_IND 0x0008
+/** GpsLocationExtended has valid vertical uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_VERT_UNC 0x0010
+/** GpsLocationExtended has valid speed uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_SPEED_UNC 0x0020
+/** GpsLocationExtended has valid heading uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_BEARING_UNC 0x0040
+/** GpsLocationExtended has valid horizontal reliability */
+#define GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY 0x0080
+/** GpsLocationExtended has valid vertical reliability */
+#define GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY 0x0100
+/** GpsLocationExtended has valid Horizontal Elliptical Uncertainty (Semi-Major Axis) */
+#define GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR 0x0200
+/** GpsLocationExtended has valid Horizontal Elliptical Uncertainty (Semi-Minor Axis) */
+#define GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR 0x0400
+/** GpsLocationExtended has valid Elliptical Horizontal Uncertainty Azimuth */
+#define GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH 0x0800
+/** GpsLocationExtended has valid gnss sv used in position data */
+#define GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA 0x1000
+/** GpsLocationExtended has valid navSolutionMask */
+#define GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK 0x2000
+/** GpsLocationExtended has valid LocPosTechMask */
+#define GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK 0x4000
+/** GpsLocationExtended has valid LocSvInfoSource */
+#define GPS_LOCATION_EXTENDED_HAS_SV_SOURCE_INFO 0x8000
+/** GpsLocationExtended has valid position dynamics data */
+#define GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA 0x10000
+/** GpsLocationExtended has GPS Time */
+#define GPS_LOCATION_EXTENDED_HAS_GPS_TIME 0x20000
+/** GpsLocationExtended has Extended Dilution of Precision */
+#define GPS_LOCATION_EXTENDED_HAS_EXT_DOP 0x40000
+/** GpsLocationExtended has North standard deviation */
+#define GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV 0x80000
+/** GpsLocationExtended has East standard deviation*/
+#define GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV 0x100000
+/** GpsLocationExtended has North Velocity */
+#define GPS_LOCATION_EXTENDED_HAS_NORTH_VEL 0x200000
+/** GpsLocationExtended has East Velocity */
+#define GPS_LOCATION_EXTENDED_HAS_EAST_VEL 0x400000
+/** GpsLocationExtended has up Velocity */
+#define GPS_LOCATION_EXTENDED_HAS_UP_VEL 0x800000
+/** GpsLocationExtended has North Velocity Uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC 0x1000000
+/** GpsLocationExtended has East Velocity Uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC 0x2000000
+/** GpsLocationExtended has up Velocity Uncertainty */
+#define GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC 0x4000000
+/** GpsLocationExtended has Clock Bias */
+#define GPS_LOCATION_EXTENDED_HAS_CLOCK_BIAS 0x8000000
+/** GpsLocationExtended has Clock Bias std deviation*/
+#define GPS_LOCATION_EXTENDED_HAS_CLOCK_BIAS_STD_DEV 0x10000000
+/** GpsLocationExtended has Clock drift*/
+#define GPS_LOCATION_EXTENDED_HAS_CLOCK_DRIFT 0x20000000
+/** GpsLocationExtended has Clock drift std deviation**/
+#define GPS_LOCATION_EXTENDED_HAS_CLOCK_DRIFT_STD_DEV 0x40000000
+/** GpsLocationExtended has leap seconds **/
+#define GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS 0x80000000
+/** GpsLocationExtended has time uncertainty **/
+#define GPS_LOCATION_EXTENDED_HAS_TIME_UNC 0x100000000
+/** GpsLocationExtended has heading rate **/
+#define GPS_LOCATION_EXTENDED_HAS_HEADING_RATE 0x200000000
+/** GpsLocationExtended has multiband signals **/
+#define GPS_LOCATION_EXTENDED_HAS_MULTIBAND 0x400000000
+/** GpsLocationExtended has sensor calibration confidence */
+#define GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE 0x800000000
+/** GpsLocationExtended has sensor calibration status */
+#define GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS 0x1000000000
+/** GpsLocationExtended has the engine type that produced this
+ * position, the bit mask will only be set when there are two
+ * or more position engines running in the system */
+#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE 0x2000000000
+ /** GpsLocationExtended has the engine mask that indicates the
+ * set of engines contribute to the fix. */
+#define GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK 0x4000000000
+/** GpsLocationExtended has dgnss correction source */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_TYPE 0x8000000000
+/** GpsLocationExtended has dgnss correction source ID */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CORRECTION_SOURCE_ID 0x10000000000
+/** GpsLocationExtended has dgnss constellation usage */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_CONSTELLATION_USAGE 0x20000000000
+/** GpsLocationExtended has dgnss ref station Id */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID 0x40000000000
+/** GpsLocationExtended has dgnss data age */
+#define GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE 0x80000000000
+ /** GpsLocationExtended has the conformityIndex computed from
+ * robust location feature. */
+#define GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX 0x100000000000
+ /** GpsLocationExtended has the llaVRPased. */
+#define GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED 0x200000000000
+/** GpsLocationExtended has the velocityVRPased. */
+#define GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED 0x400000000000
+/** GpsLocationExtended has upperTriangleFullCovMatrix. */
+#define GPS_LOCATION_EXTENDED_HAS_UPPER_TRIANGLE_FULL_COV_MATRIX 0x800000000000
+/** GpsLocationExtended has drSolutionStatusMask. */
+#define GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK 0x1000000000000
+/** GpsLocationExtended has altitudeAssumed. */
+#define GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED 0x2000000000000
+
+typedef uint32_t LocNavSolutionMask;
+/* Bitmask to specify whether SBAS ionospheric correction is used */
+#define LOC_NAV_MASK_SBAS_CORRECTION_IONO ((LocNavSolutionMask)0x0001)
+/* Bitmask to specify whether SBAS fast correction is used */
+#define LOC_NAV_MASK_SBAS_CORRECTION_FAST ((LocNavSolutionMask)0x0002)
+/**< Bitmask to specify whether SBAS long-tem correction is used */
+#define LOC_NAV_MASK_SBAS_CORRECTION_LONG ((LocNavSolutionMask)0x0004)
+/**< Bitmask to specify whether SBAS integrity information is used */
+#define LOC_NAV_MASK_SBAS_INTEGRITY ((LocNavSolutionMask)0x0008)
+/**< Bitmask to specify whether Position Report is DGNSS corrected */
+#define LOC_NAV_MASK_DGNSS_CORRECTION ((LocNavSolutionMask)0x0010)
+/**< Bitmask to specify whether Position Report is RTK corrected */
+#define LOC_NAV_MASK_RTK_CORRECTION ((LocNavSolutionMask)0x0020)
+/**< Bitmask to specify whether Position Report is PPP corrected */
+#define LOC_NAV_MASK_PPP_CORRECTION ((LocNavSolutionMask)0x0040)
+/**< Bitmask to specify whether Position Report is RTK fixed corrected */
+#define LOC_NAV_MASK_RTK_FIXED_CORRECTION ((LocNavSolutionMask)0x0080)
+/**< Bitmask specifying whether only SBAS corrected SVs are used for the fix */
+#define LOC_NAV_MASK_ONLY_SBAS_CORRECTED_SV_USED ((LocNavSolutionMask)0x0100)
+
+typedef uint32_t LocPosDataMask;
+/* Bitmask to specify whether Navigation data has Forward Acceleration */
+#define LOC_NAV_DATA_HAS_LONG_ACCEL ((LocPosDataMask)0x0001)
+/* Bitmask to specify whether Navigation data has Sideward Acceleration */
+#define LOC_NAV_DATA_HAS_LAT_ACCEL ((LocPosDataMask)0x0002)
+/* Bitmask to specify whether Navigation data has Vertical Acceleration */
+#define LOC_NAV_DATA_HAS_VERT_ACCEL ((LocPosDataMask)0x0004)
+/* Bitmask to specify whether Navigation data has Heading Rate */
+#define LOC_NAV_DATA_HAS_YAW_RATE ((LocPosDataMask)0x0008)
+/* Bitmask to specify whether Navigation data has Body pitch */
+#define LOC_NAV_DATA_HAS_PITCH ((LocPosDataMask)0x0010)
+/* Bitmask to specify whether Navigation data has Forward Acceleration Unc */
+#define LOC_NAV_DATA_HAS_LONG_ACCEL_UNC ((LocPosDataMask)0x0020)
+/* Bitmask to specify whether Navigation data has Sideward Acceleration Unc*/
+#define LOC_NAV_DATA_HAS_LAT_ACCEL_UNC ((LocPosDataMask)0x0040)
+/* Bitmask to specify whether Navigation data has Vertical Acceleration Unc*/
+#define LOC_NAV_DATA_HAS_VERT_ACCEL_UNC ((LocPosDataMask)0x0080)
+/* Bitmask to specify whether Navigation data has Heading Rate Unc*/
+#define LOC_NAV_DATA_HAS_YAW_RATE_UNC ((LocPosDataMask)0x0100)
+/* Bitmask to specify whether Navigation data has Body pitch Unc*/
+#define LOC_NAV_DATA_HAS_PITCH_UNC ((LocPosDataMask)0x0200)
+
+typedef uint32_t GnssAdditionalSystemInfoMask;
+/* Bitmask to specify whether Tauc is valid */
+#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_TAUC ((GnssAdditionalSystemInfoMask)0x0001)
+/* Bitmask to specify whether leapSec is valid */
+#define GNSS_ADDITIONAL_SYSTEMINFO_HAS_LEAP_SEC ((GnssAdditionalSystemInfoMask)0x0002)
+
+
+/** GPS PRN Range */
+#define GPS_SV_PRN_MIN 1
+#define GPS_SV_PRN_MAX 32
+#define GLO_SV_PRN_MIN 65
+#define GLO_SV_PRN_MAX 96
+#define SBAS_SV_PRN_MIN 120
+#define SBAS_SV_PRN_MAX 191
+#define QZSS_SV_PRN_MIN 193
+#define QZSS_SV_PRN_MAX 197
+#define BDS_SV_PRN_MIN 201
+#define BDS_SV_PRN_MAX 263
+#define GAL_SV_PRN_MIN 301
+#define GAL_SV_PRN_MAX 336
+#define NAVIC_SV_PRN_MIN 401
+#define NAVIC_SV_PRN_MAX 414
+#define GLO_SV_PRN_SLOT_UNKNOWN 255
+
+/* Checking svIdOneBase can be set to the corresponding bit in mask */
+#define svFitsMask(mask, svIdOneBase) \
+ ((svIdOneBase) >= 1 && (svIdOneBase) <= (sizeof(mask) << 3))
+/* Setting svIdOneBase specific bit in the mask if the bit offset fits */
+#define setSvMask(mask, svIdOneBase) \
+ if (svFitsMask(mask, svIdOneBase)) mask |= (1ULL << ((svIdOneBase) - 1))
+
+#define isValInRangeInclusive(val, min, max) ((val) >= (min) && (val) <= (max))
+#define isGloSlotUnknown(val) ((val) == GLO_SV_PRN_SLOT_UNKNOWN)
+
+typedef enum {
+ LOC_RELIABILITY_NOT_SET = 0,
+ LOC_RELIABILITY_VERY_LOW = 1,
+ LOC_RELIABILITY_LOW = 2,
+ LOC_RELIABILITY_MEDIUM = 3,
+ LOC_RELIABILITY_HIGH = 4
+}LocReliability;
+
+typedef enum {
+ LOC_IN_EMERGENCY_UNKNOWN = 0,
+ LOC_IN_EMERGENCY_SET = 1,
+ LOC_IN_EMERGENCY_NOT_SET = 2
+}LocInEmergency;
+
+typedef struct {
+ struct timespec32_t apTimeStamp;
+ /*boottime received from pps-ktimer*/
+ float apTimeStampUncertaintyMs;
+ /* timestamp uncertainty in milli seconds */
+}Gnss_ApTimeStampStructType;
+
+typedef struct {
+ uint64_t gps_sv_used_ids_mask;
+ uint64_t glo_sv_used_ids_mask;
+ uint64_t gal_sv_used_ids_mask;
+ uint64_t bds_sv_used_ids_mask;
+ uint64_t qzss_sv_used_ids_mask;
+ uint64_t navic_sv_used_ids_mask;
+} GnssSvUsedInPosition;
+
+typedef struct {
+ uint64_t gps_l1ca_sv_used_ids_mask; // GPS L1CA
+ uint64_t gps_l1c_sv_used_ids_mask; // GPS L1C
+ uint64_t gps_l2_sv_used_ids_mask; // GPS L2
+ uint64_t gps_l5_sv_used_ids_mask; // GPS L5
+ uint64_t glo_g1_sv_used_ids_mask; // GLO G1
+ uint64_t glo_g2_sv_used_ids_mask; // GLO G2
+ uint64_t gal_e1_sv_used_ids_mask; // GAL E1
+ uint64_t gal_e5a_sv_used_ids_mask; // GAL E5A
+ uint64_t gal_e5b_sv_used_ids_mask; // GAL E5B
+ uint64_t bds_b1i_sv_used_ids_mask; // BDS B1I
+ uint64_t bds_b1c_sv_used_ids_mask; // BDS B1C
+ uint64_t bds_b2i_sv_used_ids_mask; // BDS B2I
+ uint64_t bds_b2ai_sv_used_ids_mask; // BDS B2AI
+ uint64_t qzss_l1ca_sv_used_ids_mask; // QZSS L1CA
+ uint64_t qzss_l1s_sv_used_ids_mask; // QZSS L1S
+ uint64_t qzss_l2_sv_used_ids_mask; // QZSS L2
+ uint64_t qzss_l5_sv_used_ids_mask; // QZSS L5
+ uint64_t sbas_l1_sv_used_ids_mask; // SBAS L1
+ uint64_t bds_b2aq_sv_used_ids_mask; // BDS B2AQ
+} GnssSvMbUsedInPosition;
+
+/* Body Frame parameters */
+typedef struct {
+ /** Contains Body frame LocPosDataMask bits. */
+ uint32_t bodyFrameDatamask;
+ /* Forward Acceleration in body frame (m/s2)*/
+ float longAccel;
+ /** Uncertainty of Forward Acceleration in body frame */
+ float longAccelUnc;
+ /* Sideward Acceleration in body frame (m/s2)*/
+ float latAccel;
+ /** Uncertainty of Side-ward Acceleration in body frame */
+ float latAccelUnc;
+ /* Vertical Acceleration in body frame (m/s2)*/
+ float vertAccel;
+ /** Uncertainty of Vertical Acceleration in body frame */
+ float vertAccelUnc;
+ /* Heading Rate (Radians/second) */
+ float yawRate;
+ /** Uncertainty of Heading Rate */
+ float yawRateUnc;
+ /* Body pitch (Radians) */
+ float pitch;
+ /** Uncertainty of Body pitch */
+ float pitchRadUnc;
+}LocPositionDynamics;
+
+typedef struct {
+
+ /** Position dilution of precision.
+ Range: 1 (highest accuracy) to 50 (lowest accuracy) */
+ float PDOP;
+
+ /** Horizontal dilution of precision.
+ Range: 1 (highest accuracy) to 50 (lowest accuracy) */
+ float HDOP;
+
+ /** Vertical dilution of precision.
+ Range: 1 (highest accuracy) to 50 (lowest accuracy) */
+ float VDOP;
+
+ /** geometric dilution of precision.
+ Range: 1 (highest accuracy) to 50 (lowest accuracy) */
+ float GDOP;
+
+ /** time dilution of precision.
+ Range: 1 (highest accuracy) to 50 (lowest accuracy) */
+ float TDOP;
+}LocExtDOP;
+
+/* GPS Time structure */
+typedef struct {
+
+ /**< Current GPS week as calculated from midnight, Jan. 6, 1980. \n
+ - Units: Weeks */
+ uint16_t gpsWeek;
+
+ /**< Amount of time into the current GPS week. \n
+ - Units: Milliseconds */
+ uint32_t gpsTimeOfWeekMs;
+}GPSTimeStruct;
+
+typedef uint8_t CarrierPhaseAmbiguityType;
+#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_NONE ((CarrierPhaseAmbiguityType)0)
+#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FLOAT ((CarrierPhaseAmbiguityType)1)
+#define CARRIER_PHASE_AMBIGUITY_RESOLUTION_FIXED ((CarrierPhaseAmbiguityType)2)
+
+
+typedef enum {
+ LOC_DGNSS_CORR_SOURCE_TYPE_INVALID = 0, /**< Invalid DGNSS correction source type \n */
+ LOC_DGNSS_CORR_SOURCE_TYPE_RTCM = 1, /**< DGNSS correction source type RTCM \n */
+ LOC_DGNSS_CORR_SOURCE_TYPE_3GPP = 2, /**< DGNSS correction source type 3GPP \n */
+}LocDgnssCorrectionSourceType;
+
+typedef uint16_t GnssMeasUsageStatusBitMask;
+/** Used in fix */
+#define GNSS_MEAS_USED_IN_PVT ((GnssMeasUsageStatusBitMask)0x00000001ul)
+/** Measurement is Bad */
+#define GNSS_MEAS_USAGE_STATUS_BAD_MEAS ((GnssMeasUsageStatusBitMask)0x00000002ul)
+/** Measurement has too low C/N */
+#define GNSS_MEAS_USAGE_STATUS_CNO_TOO_LOW ((GnssMeasUsageStatusBitMask)0x00000004ul)
+/** Measurement has too low elevation */
+#define GNSS_MEAS_USAGE_STATUS_ELEVATION_TOO_LOW ((GnssMeasUsageStatusBitMask)0x00000008ul)
+/** No ephemeris available for this measurement */
+#define GNSS_MEAS_USAGE_STATUS_NO_EPHEMERIS ((GnssMeasUsageStatusBitMask)0x00000010ul)
+/** No corrections available for the measurement */
+#define GNSS_MEAS_USAGE_STATUS_NO_CORRECTIONS ((GnssMeasUsageStatusBitMask)0x00000020ul)
+/** Corrections has timed out for the measurement */
+#define GNSS_MEAS_USAGE_STATUS_CORRECTION_TIMEOUT ((GnssMeasUsageStatusBitMask)0x00000040ul)
+/** Measurement is unhealthy */
+#define GNSS_MEAS_USAGE_STATUS_UNHEALTHY ((GnssMeasUsageStatusBitMask)0x00000080ul)
+/** Configuration is disabled for this measurement */
+#define GNSS_MEAS_USAGE_STATUS_CONFIG_DISABLED ((GnssMeasUsageStatusBitMask)0x00000100ul)
+/** Measurement not used for other reasons */
+#define GNSS_MEAS_USAGE_STATUS_OTHER ((GnssMeasUsageStatusBitMask)0x00000200ul)
+
+/** Flags to indicate valid fields in epMeasUsageInfo */
+typedef uint16_t GnssMeasUsageInfoValidityMask;
+#define GNSS_PSEUDO_RANGE_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000001ul)
+#define GNSS_DOPPLER_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000002ul)
+#define GNSS_CARRIER_PHASE_RESIDUAL_VALID ((GnssMeasUsageInfoValidityMask)0x00000004ul)
+#define GNSS_CARRIER_PHASE_AMBIGUITY_TYPE_VALID ((GnssMeasUsageInfoValidityMask)0x00000008ul)
+
+typedef uint16_t GnssSvPolyStatusMask;
+#define GNSS_SV_POLY_SRC_ALM_CORR_V02 ((GnssSvPolyStatusMask)0x01)
+#define GNSS_SV_POLY_GLO_STR4_V02 ((GnssSvPolyStatusMask)0x02)
+#define GNSS_SV_POLY_DELETE_V02 ((GnssSvPolyStatusMask)0x04)
+#define GNSS_SV_POLY_SRC_GAL_FNAV_OR_INAV_V02 ((GnssSvPolyStatusMask)0x08)
+typedef uint16_t GnssSvPolyStatusMaskValidity;
+#define GNSS_SV_POLY_SRC_ALM_CORR_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x01)
+#define GNSS_SV_POLY_GLO_STR4_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x02)
+#define GNSS_SV_POLY_DELETE_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x04)
+#define GNSS_SV_POLY_SRC_GAL_FNAV_OR_INAV_VALID_V02 ((GnssSvPolyStatusMaskValidity)0x08)
+
+typedef struct {
+ /** Specifies GNSS signal type
+ Mandatory Field*/
+ GnssSignalTypeMask gnssSignalType;
+ /** Specifies GNSS Constellation Type
+ Mandatory Field*/
+ Gnss_LocSvSystemEnumType gnssConstellation;
+ /** Unique SV Identifier.
+ * SV Range for supported constellation is specified as below:
+ * - For GPS: 1 to 32
+ * - For GLONASS: 65 to 96
+ * - For SBAS: 120 to 158 and 183 to 191
+ * - For QZSS: 193 to 197
+ * - For BDS: 201 to 263
+ * - For GAL: 301 to 336
+ * - For NAVIC: 401 to 414 */
+ uint16_t gnssSvId;
+ /** GLONASS frequency number + 7.
+ Valid only for a GLONASS system and
+ is to be ignored for all other systems.
+ Range: 1 to 14 */
+ uint8_t gloFrequency;
+ /** Carrier phase ambiguity type. */
+ CarrierPhaseAmbiguityType carrierPhaseAmbiguityType;
+ /** Validity mask */
+ GnssMeasUsageStatusBitMask measUsageStatusMask;
+ /** Specifies measurement usage status
+ Mandatory Field*/
+ GnssMeasUsageInfoValidityMask validityMask;
+ /** Computed pseudorange residual.
+ Unit: Meters */
+ float pseudorangeResidual;
+ /** Computed doppler residual.
+ Unit: Meters/sec*/
+ float dopplerResidual;
+ /** Computed carrier phase residual.
+ Unit: Cycles*/
+ float carrierPhaseResidual;
+ /** Carrier phase ambiguity value.
+ Unit: Cycles*/
+ float carrierPhasAmbiguity;
+} GpsMeasUsageInfo;
+
+#define COV_MATRIX_SIZE 12
+/** Represents gps location extended. */
+typedef struct {
+ /** set to sizeof(GpsLocationExtended) */
+ uint32_t size;
+ /** Contains GpsLocationExtendedFlags bits. */
+ uint64_t flags;
+ /** Contains the Altitude wrt mean sea level */
+ float altitudeMeanSeaLevel;
+ /** Contains Position Dilusion of Precision. */
+ float pdop;
+ /** Contains Horizontal Dilusion of Precision. */
+ float hdop;
+ /** Contains Vertical Dilusion of Precision. */
+ float vdop;
+ /** Contains Magnetic Deviation. */
+ float magneticDeviation;
+ /** vertical uncertainty in meters */
+ float vert_unc;
+ /** speed uncertainty in m/s */
+ float speed_unc;
+ /** heading uncertainty in degrees (0 to 359.999) */
+ float bearing_unc;
+ /** horizontal reliability. */
+ LocReliability horizontal_reliability;
+ /** vertical reliability. */
+ LocReliability vertical_reliability;
+ /* Horizontal Elliptical Uncertainty (Semi-Major Axis) */
+ float horUncEllipseSemiMajor;
+ /* Horizontal Elliptical Uncertainty (Semi-Minor Axis) */
+ float horUncEllipseSemiMinor;
+ /* Elliptical Horizontal Uncertainty Azimuth */
+ float horUncEllipseOrientAzimuth;
+
+ Gnss_ApTimeStampStructType timeStamp;
+ /** Gnss sv used in position data */
+ GnssSvUsedInPosition gnss_sv_used_ids;
+ /** Gnss sv used in position data for multiband */
+ GnssSvMbUsedInPosition gnss_mb_sv_used_ids;
+ /** Nav solution mask to indicate sbas corrections */
+ LocNavSolutionMask navSolutionMask;
+ /** Position technology used in computing this fix */
+ LocPosTechMask tech_mask;
+ /** SV Info source used in computing this fix */
+ LocSvInfoSource sv_source;
+ /** Body Frame Dynamics: 4wayAcceleration and pitch set with validity */
+ GnssLocationPositionDynamics bodyFrameData;
+ /** GPS Time */
+ GPSTimeStruct gpsTime;
+ GnssSystemTime gnssSystemTime;
+ /** Dilution of precision associated with this position*/
+ LocExtDOP extDOP;
+ /** North standard deviation.
+ Unit: Meters */
+ float northStdDeviation;
+ /** East standard deviation.
+ Unit: Meters */
+ float eastStdDeviation;
+ /** North Velocity.
+ Unit: Meters/sec */
+ float northVelocity;
+ /** East Velocity.
+ Unit: Meters/sec */
+ float eastVelocity;
+ /** Up Velocity.
+ Unit: Meters/sec */
+ float upVelocity;
+ /** North Velocity standard deviation.
+ Unit: Meters/sec */
+ float northVelocityStdDeviation;
+ /** East Velocity standard deviation.
+ Unit: Meters/sec */
+ float eastVelocityStdDeviation;
+ /** Up Velocity standard deviation
+ Unit: Meters/sec */
+ float upVelocityStdDeviation;
+ /** Estimated clock bias. Unit: Nano seconds */
+ float clockbiasMeter;
+ /** Estimated clock bias std deviation. Unit: Nano seconds */
+ float clockBiasStdDeviationMeter;
+ /** Estimated clock drift. Unit: Meters/sec */
+ float clockDrift;
+ /** Estimated clock drift std deviation. Unit: Meters/sec */
+ float clockDriftStdDeviation;
+ /** Number of valid reference stations. Range:[0-4] */
+ uint8_t numValidRefStations;
+ /** Reference station(s) number */
+ uint16_t referenceStation[4];
+ /** Number of measurements received for use in fix.
+ Shall be used as maximum index in-to svUsageInfo[].
+ Set to 0, if svUsageInfo reporting is not supported.
+ Range: 0-EP_GNSS_MAX_MEAS */
+ uint8_t numOfMeasReceived;
+ /** Measurement Usage Information */
+ GpsMeasUsageInfo measUsageInfo[GNSS_SV_MAX];
+ /** Leap Seconds */
+ uint8_t leapSeconds;
+ /** Time uncertainty in milliseconds */
+ float timeUncMs;
+ /** Heading Rate is in NED frame.
+ Range: 0 to 359.999. 946
+ Unit: Degrees per Seconds */
+ float headingRateDeg;
+ /** Sensor calibration confidence percent. Range: 0 - 100 */
+ uint8_t calibrationConfidence;
+ DrCalibrationStatusMask calibrationStatus;
+ /** location engine type. When the fix. when the type is set to
+ LOC_ENGINE_SRC_FUSED, the fix is the propagated/aggregated
+ reports from all engines running on the system (e.g.:
+ DR/SPE/PPE). To check which location engine contributes to
+ the fused output, check for locOutputEngMask. */
+ LocOutputEngineType locOutputEngType;
+ /** when loc output eng type is set to fused, this field
+ indicates the set of engines contribute to the fix. */
+ PositioningEngineMask locOutputEngMask;
+
+ /** DGNSS Correction Source for position report: RTCM, 3GPP
+ * etc. */
+ LocDgnssCorrectionSourceType dgnssCorrectionSourceType;
+
+ /** If DGNSS is used, the SourceID is a 32bit number identifying
+ * the DGNSS source ID */
+ uint32_t dgnssCorrectionSourceID;
+
+ /** If DGNSS is used, which constellation was DGNSS used for to
+ * produce the pos report. */
+ GnssConstellationTypeMask dgnssConstellationUsage;
+
+ /** If DGNSS is used, DGNSS Reference station ID used for
+ * position report */
+ uint16_t dgnssRefStationId;
+
+ /** If DGNSS is used, DGNSS data age in milli-seconds */
+ uint32_t dgnssDataAgeMsec;
+
+ /** When robust location is enabled, this field
+ * will how well the various input data considered for
+ * navigation solution conform to expectations.
+ * Range: 0 (least conforming) to 1 (most conforming) */
+ float conformityIndex;
+ GnssLocationPositionDynamicsExt bodyFrameDataExt;
+ /** VRR-based latitude/longitude/altitude */
+ LLAInfo llaVRPBased;
+ /** VRR-based east, north, and up velocity */
+ float enuVelocityVRPBased[3];
+ /** Upper triangle elements of full matrix of position and
+ velocity estimate in ECEF
+
+ The full covariance matrix of PPE position
+ (x, y, z in ECEF, in the unit of meters) estimate is a 3x3 matrix
+ | px,x px,y px,z |
+ | py,x py,y py,z |
+ | pz,x pz,y pz,z |
+
+ The full covariance matrix of PPE velocity
+ (vx,vy, vz in ECEF, in the unit of m/s) estimate is a 3x3 matrix
+ | pvx,vx pvx,vy pvx,vz |
+ | pvy,vx pvy,vy pvy,vz |
+ | pvz,vx pvz,vy pvz,vz |
+
+ upperTriangleFullCovMatrix =
+ { px,x, px,y, px,z, py,y, py,z, pz,z, pvx,vx, pvx,vy, pvx,vz, pvy,vy, pvy,vz, pvz,vz}
+ Uint: px,x, px,y, px,z, py,y, py,z, pz,z is in meter
+ pvx,vx, pvx,vy, pvx,vz, pvy,vy, pvy,vz, pvz,vz is in meters/seconds
+ */
+ float upperTriangleFullCovMatrix[COV_MATRIX_SIZE];
+ DrSolutionStatusMask drSolutionStatusMask;
+ /** When this field is valid, it will indicates whether altitude
+ * is assumed or calculated.
+ * false: Altitude is calculated.
+ * true: Altitude is assumed; there may not be enough
+ * satellites to determine the precise altitude. */
+ bool altitudeAssumed;
+} GpsLocationExtended;
+
+// struct that contains complete position info from engine
+typedef struct {
+ UlpLocation location;
+ GpsLocationExtended locationExtended;
+ enum loc_sess_status sessionStatus;
+} EngineLocationInfo;
+
+// Nmea sentence types mask
+typedef uint32_t NmeaSentenceTypesMask;
+#define LOC_NMEA_MASK_GGA_V02 ((NmeaSentenceTypesMask)0x00000001) /**< Enable GGA type */
+#define LOC_NMEA_MASK_RMC_V02 ((NmeaSentenceTypesMask)0x00000002) /**< Enable RMC type */
+#define LOC_NMEA_MASK_GSV_V02 ((NmeaSentenceTypesMask)0x00000004) /**< Enable GSV type */
+#define LOC_NMEA_MASK_GSA_V02 ((NmeaSentenceTypesMask)0x00000008) /**< Enable GSA type */
+#define LOC_NMEA_MASK_VTG_V02 ((NmeaSentenceTypesMask)0x00000010) /**< Enable VTG type */
+#define LOC_NMEA_MASK_PQXFI_V02 ((NmeaSentenceTypesMask)0x00000020) /**< Enable PQXFI type */
+#define LOC_NMEA_MASK_PSTIS_V02 ((NmeaSentenceTypesMask)0x00000040) /**< Enable PSTIS type */
+#define LOC_NMEA_MASK_GLGSV_V02 ((NmeaSentenceTypesMask)0x00000080) /**< Enable GLGSV type */
+#define LOC_NMEA_MASK_GNGSA_V02 ((NmeaSentenceTypesMask)0x00000100) /**< Enable GNGSA type */
+#define LOC_NMEA_MASK_GNGNS_V02 ((NmeaSentenceTypesMask)0x00000200) /**< Enable GNGNS type */
+#define LOC_NMEA_MASK_GARMC_V02 ((NmeaSentenceTypesMask)0x00000400) /**< Enable GARMC type */
+#define LOC_NMEA_MASK_GAGSV_V02 ((NmeaSentenceTypesMask)0x00000800) /**< Enable GAGSV type */
+#define LOC_NMEA_MASK_GAGSA_V02 ((NmeaSentenceTypesMask)0x00001000) /**< Enable GAGSA type */
+#define LOC_NMEA_MASK_GAVTG_V02 ((NmeaSentenceTypesMask)0x00002000) /**< Enable GAVTG type */
+#define LOC_NMEA_MASK_GAGGA_V02 ((NmeaSentenceTypesMask)0x00004000) /**< Enable GAGGA type */
+#define LOC_NMEA_MASK_PQGSA_V02 ((NmeaSentenceTypesMask)0x00008000) /**< Enable PQGSA type */
+#define LOC_NMEA_MASK_PQGSV_V02 ((NmeaSentenceTypesMask)0x00010000) /**< Enable PQGSV type */
+#define LOC_NMEA_MASK_DEBUG_V02 ((NmeaSentenceTypesMask)0x00020000) /**< Enable DEBUG type */
+#define LOC_NMEA_MASK_GPDTM_V02 ((NmeaSentenceTypesMask)0x00040000) /**< Enable GPDTM type */
+#define LOC_NMEA_MASK_GNGGA_V02 ((NmeaSentenceTypesMask)0x00080000) /**< Enable GNGGA type */
+#define LOC_NMEA_MASK_GNRMC_V02 ((NmeaSentenceTypesMask)0x00100000) /**< Enable GNRMC type */
+#define LOC_NMEA_MASK_GNVTG_V02 ((NmeaSentenceTypesMask)0x00200000) /**< Enable GNVTG type */
+#define LOC_NMEA_MASK_GAGNS_V02 ((NmeaSentenceTypesMask)0x00400000) /**< Enable GAGNS type */
+#define LOC_NMEA_MASK_GBGGA_V02 ((NmeaSentenceTypesMask)0x00800000) /**< Enable GBGGA type */
+#define LOC_NMEA_MASK_GBGSA_V02 ((NmeaSentenceTypesMask)0x01000000) /**< Enable GBGSA type */
+#define LOC_NMEA_MASK_GBGSV_V02 ((NmeaSentenceTypesMask)0x02000000) /**< Enable GBGSV type */
+#define LOC_NMEA_MASK_GBRMC_V02 ((NmeaSentenceTypesMask)0x04000000) /**< Enable GBRMC type */
+#define LOC_NMEA_MASK_GBVTG_V02 ((NmeaSentenceTypesMask)0x08000000) /**< Enable GBVTG type */
+#define LOC_NMEA_MASK_GQGSV_V02 ((NmeaSentenceTypesMask)0x10000000) /**< Enable GQGSV type */
+#define LOC_NMEA_MASK_GIGSV_V02 ((NmeaSentenceTypesMask)0x20000000) /**< Enable GIGSV type */
+#define LOC_NMEA_MASK_GNDTM_V02 ((NmeaSentenceTypesMask)0x40000000) /**< Enable GNDTM type */
+#define LOC_NMEA_MASK_TAGBLOCK_V02 ((NmeaSentenceTypesMask)0x80000000) /**< Enable TAGBLOCK type */
+
+
+// all bitmasks of general supported NMEA sentenses - debug is not part of this
+#define LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK (LOC_NMEA_MASK_GGA_V02 | LOC_NMEA_MASK_RMC_V02 | \
+ LOC_NMEA_MASK_GSV_V02 | LOC_NMEA_MASK_GSA_V02 | LOC_NMEA_MASK_VTG_V02 | \
+ LOC_NMEA_MASK_PQXFI_V02 | LOC_NMEA_MASK_PSTIS_V02 | LOC_NMEA_MASK_GLGSV_V02 | \
+ LOC_NMEA_MASK_GNGSA_V02 | LOC_NMEA_MASK_GNGNS_V02 | LOC_NMEA_MASK_GARMC_V02 | \
+ LOC_NMEA_MASK_GAGSV_V02 | LOC_NMEA_MASK_GAGSA_V02 | LOC_NMEA_MASK_GAVTG_V02 | \
+ LOC_NMEA_MASK_GAGGA_V02 | LOC_NMEA_MASK_PQGSA_V02 | LOC_NMEA_MASK_PQGSV_V02 | \
+ LOC_NMEA_MASK_GPDTM_V02 | LOC_NMEA_MASK_GNGGA_V02 | LOC_NMEA_MASK_GNRMC_V02 | \
+ LOC_NMEA_MASK_GNVTG_V02 | LOC_NMEA_MASK_GAGNS_V02 | LOC_NMEA_MASK_GBGGA_V02 | \
+ LOC_NMEA_MASK_GBGSA_V02 | LOC_NMEA_MASK_GBGSV_V02 | LOC_NMEA_MASK_GBRMC_V02 | \
+ LOC_NMEA_MASK_GBVTG_V02 | LOC_NMEA_MASK_GQGSV_V02 | LOC_NMEA_MASK_GIGSV_V02 | \
+ LOC_NMEA_MASK_GNDTM_V02)
+
+typedef enum {
+ LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC = 0,
+ LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM,
+ LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU,
+ LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
+ LOC_ENG_IF_REQUEST_SENDER_ID_MODEM,
+ LOC_ENG_IF_REQUEST_SENDER_ID_UNKNOWN
+} loc_if_req_sender_id_e_type;
+
+
+#define smaller_of(a, b) (((a) > (b)) ? (b) : (a))
+#define MAX_APN_LEN 100
+
+// This will be overridden by the individual adapters
+// if necessary.
+#define DEFAULT_IMPL(rtv) \
+{ \
+ LOC_LOGD("%s: default implementation invoked", __func__); \
+ return rtv; \
+}
+
+enum loc_api_adapter_err {
+ LOC_API_ADAPTER_ERR_SUCCESS = 0,
+ LOC_API_ADAPTER_ERR_GENERAL_FAILURE = 1,
+ LOC_API_ADAPTER_ERR_UNSUPPORTED = 2,
+ LOC_API_ADAPTER_ERR_INVALID_HANDLE = 4,
+ LOC_API_ADAPTER_ERR_INVALID_PARAMETER = 5,
+ LOC_API_ADAPTER_ERR_ENGINE_BUSY = 6,
+ LOC_API_ADAPTER_ERR_PHONE_OFFLINE = 7,
+ LOC_API_ADAPTER_ERR_TIMEOUT = 8,
+ LOC_API_ADAPTER_ERR_SERVICE_NOT_PRESENT = 9,
+ LOC_API_ADAPTER_ERR_INTERNAL = 10,
+
+ /* equating engine down to phone offline, as they are the same errror */
+ LOC_API_ADAPTER_ERR_ENGINE_DOWN = LOC_API_ADAPTER_ERR_PHONE_OFFLINE,
+ LOC_API_ADAPTER_ERR_FAILURE = 101,
+ LOC_API_ADAPTER_ERR_UNKNOWN
+};
+
+enum loc_api_adapter_event_index {
+ LOC_API_ADAPTER_REPORT_POSITION = 0, // Position report comes in loc_parsed_position_s_type
+ LOC_API_ADAPTER_REPORT_SATELLITE, // Satellite in view report
+ LOC_API_ADAPTER_REPORT_NMEA_1HZ, // NMEA report at 1HZ rate
+ LOC_API_ADAPTER_REPORT_NMEA_POSITION, // NMEA report at position report rate
+ LOC_API_ADAPTER_REQUEST_NI_NOTIFY_VERIFY, // NI notification/verification request
+ LOC_API_ADAPTER_REQUEST_ASSISTANCE_DATA, // Assistance data, eg: time, predicted orbits request
+ LOC_API_ADAPTER_REQUEST_LOCATION_SERVER, // Request for location server
+ LOC_API_ADAPTER_REPORT_IOCTL, // Callback report for loc_ioctl
+ LOC_API_ADAPTER_REPORT_STATUS, // Misc status report: eg, engine state
+ LOC_API_ADAPTER_REQUEST_WIFI, //
+ LOC_API_ADAPTER_SENSOR_STATUS, //
+ LOC_API_ADAPTER_REQUEST_TIME_SYNC, //
+ LOC_API_ADAPTER_REPORT_SPI, //
+ LOC_API_ADAPTER_REPORT_NI_GEOFENCE, //
+ LOC_API_ADAPTER_GEOFENCE_GEN_ALERT, //
+ LOC_API_ADAPTER_REPORT_GENFENCE_BREACH, //
+ LOC_API_ADAPTER_PEDOMETER_CTRL, //
+ LOC_API_ADAPTER_MOTION_CTRL, //
+ LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA, // Wifi ap data
+ LOC_API_ADAPTER_BATCH_FULL, // Batching on full
+ LOC_API_ADAPTER_BATCHED_POSITION_REPORT, // Batching on fix
+ LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT, //
+ LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT, // GNSS Measurement Report
+ LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT, // GNSS SV Polynomial Report
+ LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ, // GDT upload start request
+ LOC_API_ADAPTER_GDT_UPLOAD_END_REQ, // GDT upload end request
+ LOC_API_ADAPTER_GNSS_MEASUREMENT, // GNSS Measurement report
+ LOC_API_ADAPTER_REQUEST_TIMEZONE, // Timezone injection request
+ LOC_API_ADAPTER_REPORT_GENFENCE_DWELL_REPORT, // Geofence dwell report
+ LOC_API_ADAPTER_REQUEST_SRN_DATA, // request srn data from AP
+ LOC_API_ADAPTER_REQUEST_POSITION_INJECTION, // Position injection request
+ LOC_API_ADAPTER_BATCH_STATUS, // batch status
+ LOC_API_ADAPTER_FDCL_SERVICE_REQ, // FDCL service request
+ LOC_API_ADAPTER_REPORT_UNPROPAGATED_POSITION, // Unpropagated Position report
+ LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ, // BS observation data request
+ LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT, // GNSS SV Ephemeris Report
+ LOC_API_ADAPTER_LOC_SYSTEM_INFO, // Location system info event
+ LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT, // GNSS SV nHz measurement report
+ LOC_API_ADAPTER_EVENT_REPORT_INFO, // Event report info
+ LOC_API_ADAPTER_LATENCY_INFORMATION_REPORT, // Latency information report
+ LOC_API_ADAPTER_EVENT_MAX
+};
+
+#define LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_POSITION)
+#define LOC_API_ADAPTER_BIT_SATELLITE_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_SATELLITE)
+#define LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_NMEA_1HZ)
+#define LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_NMEA_POSITION)
+#define LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST (1ULL<<LOC_API_ADAPTER_REQUEST_NI_NOTIFY_VERIFY)
+#define LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST (1ULL<<LOC_API_ADAPTER_REQUEST_ASSISTANCE_DATA)
+#define LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST (1ULL<<LOC_API_ADAPTER_REQUEST_LOCATION_SERVER)
+#define LOC_API_ADAPTER_BIT_IOCTL_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_IOCTL)
+#define LOC_API_ADAPTER_BIT_STATUS_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_STATUS)
+#define LOC_API_ADAPTER_BIT_REQUEST_WIFI (1ULL<<LOC_API_ADAPTER_REQUEST_WIFI)
+#define LOC_API_ADAPTER_BIT_SENSOR_STATUS (1ULL<<LOC_API_ADAPTER_SENSOR_STATUS)
+#define LOC_API_ADAPTER_BIT_REQUEST_TIME_SYNC (1ULL<<LOC_API_ADAPTER_REQUEST_TIME_SYNC)
+#define LOC_API_ADAPTER_BIT_REPORT_SPI (1ULL<<LOC_API_ADAPTER_REPORT_SPI)
+#define LOC_API_ADAPTER_BIT_REPORT_NI_GEOFENCE (1ULL<<LOC_API_ADAPTER_REPORT_NI_GEOFENCE)
+#define LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT (1ULL<<LOC_API_ADAPTER_GEOFENCE_GEN_ALERT)
+#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_BREACH (1ULL<<LOC_API_ADAPTER_REPORT_GENFENCE_BREACH)
+#define LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT (1ULL<<LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT)
+#define LOC_API_ADAPTER_BIT_PEDOMETER_CTRL (1ULL<<LOC_API_ADAPTER_PEDOMETER_CTRL)
+#define LOC_API_ADAPTER_BIT_MOTION_CTRL (1ULL<<LOC_API_ADAPTER_MOTION_CTRL)
+#define LOC_API_ADAPTER_BIT_REQUEST_WIFI_AP_DATA (1ULL<<LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA)
+#define LOC_API_ADAPTER_BIT_BATCH_FULL (1ULL<<LOC_API_ADAPTER_BATCH_FULL)
+#define LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_BATCHED_POSITION_REPORT)
+#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT_REPORT (1ULL<<LOC_API_ADAPTER_GNSS_MEASUREMENT_REPORT)
+#define LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT (1ULL<<LOC_API_ADAPTER_GNSS_SV_POLYNOMIAL_REPORT)
+#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_BEGIN_REQ (1ULL<<LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ)
+#define LOC_API_ADAPTER_BIT_GDT_UPLOAD_END_REQ (1ULL<<LOC_API_ADAPTER_GDT_UPLOAD_END_REQ)
+#define LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT (1ULL<<LOC_API_ADAPTER_GNSS_MEASUREMENT)
+#define LOC_API_ADAPTER_BIT_REQUEST_TIMEZONE (1ULL<<LOC_API_ADAPTER_REQUEST_TIMEZONE)
+#define LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL (1ULL<<LOC_API_ADAPTER_REPORT_GENFENCE_DWELL_REPORT)
+#define LOC_API_ADAPTER_BIT_REQUEST_SRN_DATA (1ULL<<LOC_API_ADAPTER_REQUEST_SRN_DATA)
+#define LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST (1ULL<<LOC_API_ADAPTER_REQUEST_POSITION_INJECTION)
+#define LOC_API_ADAPTER_BIT_BATCH_STATUS (1ULL<<LOC_API_ADAPTER_BATCH_STATUS)
+#define LOC_API_ADAPTER_BIT_FDCL_SERVICE_REQ (1ULL<<LOC_API_ADAPTER_FDCL_SERVICE_REQ)
+#define LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT (1ULL<<LOC_API_ADAPTER_REPORT_UNPROPAGATED_POSITION)
+#define LOC_API_ADAPTER_BIT_BS_OBS_DATA_SERVICE_REQ (1ULL<<LOC_API_ADAPTER_BS_OBS_DATA_SERVICE_REQ)
+#define LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT (1ULL<<LOC_API_ADAPTER_GNSS_SV_EPHEMERIS_REPORT)
+#define LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO (1ULL<<LOC_API_ADAPTER_LOC_SYSTEM_INFO)
+#define LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT (1ULL<<LOC_API_ADAPTER_GNSS_NHZ_MEASUREMENT_REPORT)
+#define LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO (1ULL<<LOC_API_ADAPTER_EVENT_REPORT_INFO)
+#define LOC_API_ADAPTER_BIT_LATENCY_INFORMATION (1ULL<<LOC_API_ADAPTER_LATENCY_INFORMATION_REPORT)
+
+typedef uint64_t LOC_API_ADAPTER_EVENT_MASK_T;
+
+typedef enum loc_api_adapter_msg_to_check_supported {
+ LOC_API_ADAPTER_MESSAGE_LOCATION_BATCHING, // Batching 1.0
+ LOC_API_ADAPTER_MESSAGE_BATCHED_GENFENCE_BREACH, // Geofence Batched Breach
+ LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING, // DBT 2.0
+ LOC_API_ADAPTER_MESSAGE_ADAPTIVE_LOCATION_BATCHING, // Batching 1.5
+ LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING, // Batching 2.0
+ LOC_API_ADAPTER_MESSAGE_UPDATE_TBF_ON_THE_FLY, // Updating Tracking TBF On The Fly
+ LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING, // Outdoor Trip Batching
+
+ LOC_API_ADAPTER_MESSAGE_MAX
+} LocCheckingMessagesID;
+
+typedef int IzatDevId_t;
+
+typedef uint32_t LOC_GPS_LOCK_MASK;
+#define isGpsLockNone(lock) ((lock) == 0)
+#define isGpsLockMO(lock) ((lock) & ((LOC_GPS_LOCK_MASK)1))
+#define isGpsLockMT(lock) ((lock) & ((LOC_GPS_LOCK_MASK)2))
+#define isGpsLockAll(lock) (((lock) & ((LOC_GPS_LOCK_MASK)3)) == 3)
+
+/* ***********************************************
+** Satellite Measurement and Satellite Polynomial
+** structure definitions
+** ***********************************************
+*/
+#define GNSS_SV_POLY_VELOCITY_COEF_MAX_SIZE 12
+#define GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE 3
+#define GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE 9
+#define GNSS_SV_POLY_SV_CLKBIAS_COEFF_MAX_SIZE 4
+/** Max number of GNSS SV measurement */
+#define GNSS_LOC_SV_MEAS_LIST_MAX_SIZE 128
+
+enum ulp_gnss_sv_measurement_valid_flags{
+
+ ULP_GNSS_SV_MEAS_GPS_TIME = 0,
+ ULP_GNSS_SV_MEAS_PSUEDO_RANGE,
+ ULP_GNSS_SV_MEAS_MS_IN_WEEK,
+ ULP_GNSS_SV_MEAS_SUB_MSEC,
+ ULP_GNSS_SV_MEAS_CARRIER_PHASE,
+ ULP_GNSS_SV_MEAS_DOPPLER_SHIFT,
+ ULP_GNSS_SV_MEAS_CNO,
+ ULP_GNSS_SV_MEAS_LOSS_OF_LOCK,
+
+ ULP_GNSS_SV_MEAS_MAX_VALID_FLAGS
+};
+
+#define ULP_GNSS_SV_MEAS_BIT_GPS_TIME (1<<ULP_GNSS_SV_MEAS_GPS_TIME)
+#define ULP_GNSS_SV_MEAS_BIT_PSUEDO_RANGE (1<<ULP_GNSS_SV_MEAS_PSUEDO_RANGE)
+#define ULP_GNSS_SV_MEAS_BIT_MS_IN_WEEK (1<<ULP_GNSS_SV_MEAS_MS_IN_WEEK)
+#define ULP_GNSS_SV_MEAS_BIT_SUB_MSEC (1<<ULP_GNSS_SV_MEAS_SUB_MSEC)
+#define ULP_GNSS_SV_MEAS_BIT_CARRIER_PHASE (1<<ULP_GNSS_SV_MEAS_CARRIER_PHASE)
+#define ULP_GNSS_SV_MEAS_BIT_DOPPLER_SHIFT (1<<ULP_GNSS_SV_MEAS_DOPPLER_SHIFT)
+#define ULP_GNSS_SV_MEAS_BIT_CNO (1<<ULP_GNSS_SV_MEAS_CNO)
+#define ULP_GNSS_SV_MEAS_BIT_LOSS_OF_LOCK (1<<ULP_GNSS_SV_MEAS_LOSS_OF_LOCK)
+
+enum ulp_gnss_sv_poly_valid_flags{
+
+ ULP_GNSS_SV_POLY_GLO_FREQ = 0,
+ ULP_GNSS_SV_POLY_T0,
+ ULP_GNSS_SV_POLY_IODE,
+ ULP_GNSS_SV_POLY_FLAG,
+ ULP_GNSS_SV_POLY_POLYCOEFF_XYZ0,
+ ULP_GNSS_SV_POLY_POLYCOEFF_XYZN,
+ ULP_GNSS_SV_POLY_POLYCOEFF_OTHER,
+ ULP_GNSS_SV_POLY_SV_POSUNC,
+ ULP_GNSS_SV_POLY_IONODELAY,
+ ULP_GNSS_SV_POLY_IONODOT,
+ ULP_GNSS_SV_POLY_SBAS_IONODELAY,
+ ULP_GNSS_SV_POLY_SBAS_IONODOT,
+ ULP_GNSS_SV_POLY_TROPODELAY,
+ ULP_GNSS_SV_POLY_ELEVATION,
+ ULP_GNSS_SV_POLY_ELEVATIONDOT,
+ ULP_GNSS_SV_POLY_ELEVATIONUNC,
+ ULP_GNSS_SV_POLY_VELO_COEFF,
+ ULP_GNSS_SV_POLY_ENHANCED_IOD,
+ ULP_GNSS_SV_POLY_GPS_ISC_L1CA,
+ ULP_GNSS_SV_POLY_GPS_ISC_L2C,
+ ULP_GNSS_SV_POLY_GPS_ISC_L5I5,
+ ULP_GNSS_SV_POLY_GPS_ISC_L5Q5,
+ ULP_GNSS_SV_POLY_GPS_TGD,
+ ULP_GNSS_SV_POLY_GLO_TGD_G1G2,
+ ULP_GNSS_SV_POLY_BDS_TGD_B1,
+ ULP_GNSS_SV_POLY_BDS_TGD_B2,
+ ULP_GNSS_SV_POLY_BDS_TGD_B2A,
+ ULP_GNSS_SV_POLY_BDS_ISC_B2A,
+ ULP_GNSS_SV_POLY_GAL_BGD_E1E5A,
+ ULP_GNSS_SV_POLY_GAL_BGD_E1E5B,
+ ULP_GNSS_SV_POLY_NAVIC_TGD_L5
+};
+
+#define ULP_GNSS_SV_POLY_BIT_GLO_FREQ (1<<ULP_GNSS_SV_POLY_GLO_FREQ)
+#define ULP_GNSS_SV_POLY_BIT_T0 (1<<ULP_GNSS_SV_POLY_T0)
+#define ULP_GNSS_SV_POLY_BIT_IODE (1<<ULP_GNSS_SV_POLY_IODE)
+#define ULP_GNSS_SV_POLY_BIT_FLAG (1<<ULP_GNSS_SV_POLY_FLAG)
+#define ULP_GNSS_SV_POLY_BIT_POLYCOEFF_XYZ0 (1<<ULP_GNSS_SV_POLY_POLYCOEFF_XYZ0)
+#define ULP_GNSS_SV_POLY_BIT_POLYCOEFF_XYZN (1<<ULP_GNSS_SV_POLY_POLYCOEFF_XYZN)
+#define ULP_GNSS_SV_POLY_BIT_POLYCOEFF_OTHER (1<<ULP_GNSS_SV_POLY_POLYCOEFF_OTHER)
+#define ULP_GNSS_SV_POLY_BIT_SV_POSUNC (1<<ULP_GNSS_SV_POLY_SV_POSUNC)
+#define ULP_GNSS_SV_POLY_BIT_IONODELAY (1<<ULP_GNSS_SV_POLY_IONODELAY)
+#define ULP_GNSS_SV_POLY_BIT_IONODOT (1<<ULP_GNSS_SV_POLY_IONODOT)
+#define ULP_GNSS_SV_POLY_BIT_SBAS_IONODELAY (1<<ULP_GNSS_SV_POLY_SBAS_IONODELAY)
+#define ULP_GNSS_SV_POLY_BIT_SBAS_IONODOT (1<<ULP_GNSS_SV_POLY_SBAS_IONODOT)
+#define ULP_GNSS_SV_POLY_BIT_TROPODELAY (1<<ULP_GNSS_SV_POLY_TROPODELAY)
+#define ULP_GNSS_SV_POLY_BIT_ELEVATION (1<<ULP_GNSS_SV_POLY_ELEVATION)
+#define ULP_GNSS_SV_POLY_BIT_ELEVATIONDOT (1<<ULP_GNSS_SV_POLY_ELEVATIONDOT)
+#define ULP_GNSS_SV_POLY_BIT_ELEVATIONUNC (1<<ULP_GNSS_SV_POLY_ELEVATIONUNC)
+#define ULP_GNSS_SV_POLY_BIT_VELO_COEFF (1<<ULP_GNSS_SV_POLY_VELO_COEFF)
+#define ULP_GNSS_SV_POLY_BIT_ENHANCED_IOD (1<<ULP_GNSS_SV_POLY_ENHANCED_IOD)
+#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L1CA (1<<ULP_GNSS_SV_POLY_GPS_ISC_L1CA)
+#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L2C (1<<ULP_GNSS_SV_POLY_GPS_ISC_L2C)
+#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5I5 (1<<ULP_GNSS_SV_POLY_GPS_ISC_L5I5)
+#define ULP_GNSS_SV_POLY_BIT_GPS_ISC_L5Q5 (1<<ULP_GNSS_SV_POLY_GPS_ISC_L5Q5)
+#define ULP_GNSS_SV_POLY_BIT_GPS_TGD (1<<ULP_GNSS_SV_POLY_GPS_TGD)
+#define ULP_GNSS_SV_POLY_BIT_GLO_TGD_G1G2 (1<<ULP_GNSS_SV_POLY_GLO_TGD_G1G2)
+#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B1 (1<<ULP_GNSS_SV_POLY_BDS_TGD_B1)
+#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2 (1<<ULP_GNSS_SV_POLY_BDS_TGD_B2)
+#define ULP_GNSS_SV_POLY_BIT_BDS_TGD_B2A (1<<ULP_GNSS_SV_POLY_BDS_TGD_B2A)
+#define ULP_GNSS_SV_POLY_BIT_BDS_ISC_B2A (1<<ULP_GNSS_SV_POLY_BDS_ISC_B2A)
+#define ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5A (1<<ULP_GNSS_SV_POLY_GAL_BGD_E1E5A)
+#define ULP_GNSS_SV_POLY_BIT_GAL_BGD_E1E5B (1<<ULP_GNSS_SV_POLY_GAL_BGD_E1E5B)
+#define ULP_GNSS_SV_POLY_BIT_NAVIC_TGD_L5 (1<<ULP_GNSS_SV_POLY_NAVIC_TGD_L5)
+
+typedef enum
+{
+ GNSS_LOC_FREQ_SOURCE_INVALID = 0,
+ /**< Source of the frequency is invalid */
+ GNSS_LOC_FREQ_SOURCE_EXTERNAL = 1,
+ /**< Source of the frequency is from external injection */
+ GNSS_LOC_FREQ_SOURCE_PE_CLK_REPORT = 2,
+ /**< Source of the frequency is from Navigation engine */
+ GNSS_LOC_FREQ_SOURCE_UNKNOWN = 3
+ /**< Source of the frequency is unknown */
+} Gnss_LocSourceofFreqEnumType;
+
+typedef struct
+{
+ uint32_t size;
+ float clockDrift;
+ /**< Receiver clock Drift \n
+ - Units: meter per sec \n
+ */
+ float clockDriftUnc;
+ /**< Receiver clock Drift uncertainty \n
+ - Units: meter per sec \n
+ */
+ Gnss_LocSourceofFreqEnumType sourceOfFreq;
+}Gnss_LocRcvrClockFrequencyInfoStructType;
+
+typedef struct
+{
+ uint32_t size;
+ uint8_t leapSec;
+ /**< GPS time leap second delta to UTC time \n
+ - Units: sec \n
+ */
+ uint8_t leapSecUnc;
+ /**< Uncertainty for GPS leap second \n
+ - Units: sec \n
+ */
+}Gnss_LeapSecondInfoStructType;
+
+typedef enum
+{
+ GNSS_LOC_SYS_TIME_BIAS_VALID = 0x01,
+ /**< System time bias valid */
+ GNSS_LOC_SYS_TIME_BIAS_UNC_VALID = 0x02,
+ /**< System time bias uncertainty valid */
+}Gnss_LocInterSystemBiasValidMaskType;
+
+typedef struct
+{
+ uint32_t size;
+ uint32_t validMask;
+ /* Validity mask as per Gnss_LocInterSystemBiasValidMaskType */
+
+ float timeBias;
+ /**< System-1 to System-2 Time Bias \n
+ - Units: msec \n
+ */
+ float timeBiasUnc;
+ /**< System-1 to System-2 Time Bias uncertainty \n
+ - Units: msec \n
+ */
+} Gnss_InterSystemBiasStructType;
+
+
+typedef struct {
+
+ uint32_t size;
+
+ uint8_t systemRtc_valid;
+ /**< Validity indicator for System RTC */
+
+ uint64_t systemRtcMs;
+ /**< Platform system RTC value \n
+ - Units: msec \n
+ */
+
+}Gnss_LocGnssTimeExtStructType;
+
+typedef enum
+{
+ GNSS_LOC_MEAS_STATUS_NULL = 0x00000000,
+ /**< No information state */
+ GNSS_LOC_MEAS_STATUS_SM_VALID = 0x00000001,
+ /**< Code phase is known */
+ GNSS_LOC_MEAS_STATUS_SB_VALID = 0x00000002,
+ /**< Sub-bit time is known */
+ GNSS_LOC_MEAS_STATUS_MS_VALID = 0x00000004,
+ /**< Satellite time is known */
+ GNSS_LOC_MEAS_STATUS_BE_CONFIRM = 0x00000008,
+ /**< Bit edge is confirmed from signal */
+ GNSS_LOC_MEAS_STATUS_VELOCITY_VALID = 0x00000010,
+ /**< Satellite Doppler measured */
+ GNSS_LOC_MEAS_STATUS_VELOCITY_FINE = 0x00000020,
+ /**< TRUE: Fine Doppler measured, FALSE: Coarse Doppler measured */
+ GNSS_LOC_MEAS_STATUS_LP_VALID = 0x00000040,
+ /**< TRUE/FALSE -- Lock Point is valid/invalid */
+ GNSS_LOC_MEAS_STATUS_LP_POS_VALID = 0x00000080,
+ /**< TRUE/FALSE -- Lock Point is positive/negative */
+ GNSS_LOC_MEAS_STATUS_FROM_RNG_DIFF = 0x00000200,
+ /**< Range update from Satellite differences */
+ GNSS_LOC_MEAS_STATUS_FROM_VE_DIFF = 0x00000400,
+ /**< Doppler update from Satellite differences */
+ GNSS_LOC_MEAS_STATUS_DONT_USE_X = 0x00000800,
+ /**< Don't use measurement if bit is set */
+ GNSS_LOC_MEAS_STATUS_DONT_USE_M = 0x00001000,
+ /**< Don't use measurement if bit is set */
+ GNSS_LOC_MEAS_STATUS_DONT_USE_D = 0x00002000,
+ /**< Don't use measurement if bit is set */
+ GNSS_LOC_MEAS_STATUS_DONT_USE_S = 0x00004000,
+ /**< Don't use measurement if bit is set */
+ GNSS_LOC_MEAS_STATUS_DONT_USE_P = 0x00008000,
+ /**< Don't use measurement if bit is set */
+ GNSS_LOC_MEAS_STATUS_GNSS_FRESH_MEAS = 0x08000000
+ /**< TRUE -- Fresh GNSS measurement observed in last second */
+}Gnss_LocSvMeasStatusMaskType;
+
+typedef struct
+{
+ uint32_t size;
+ uint32_t svMs;
+ /**< Satellite time milisecond.\n
+ For GPS, BDS, GAL range of 0 thru (604800000-1) \n
+ For GLONASS range of 0 thru (86400000-1) \n
+ Valid when PD_LOC_MEAS_STATUS_MS_VALID bit is set in measurement status \n
+ Note: All SV times in the current measurement block are alredy propagated to common reference time epoch. \n
+ - Units: msec \n
+ */
+ float svSubMs;
+ /**<Satellite time sub-millisecond. \n
+ Total SV Time = svMs + svSubMs \n
+ - Units: msec \n
+ */
+ float svTimeUncMs;
+ /**< Satellite Time uncertainty \n
+ - Units: msec \n
+ */
+ float dopplerShift;
+ /**< Satellite Doppler \n
+ - Units: meter per sec \n
+ */
+ float dopplerShiftUnc;
+ /**< Satellite Doppler uncertainty\n
+ - Units: meter per sec \n
+ */
+}Gnss_LocSVTimeSpeedStructType;
+
+typedef enum
+{
+ GNSS_SV_STATE_IDLE = 0,
+ GNSS_SV_STATE_SEARCH = 1,
+ GNSS_SV_STATE_SEARCH_VERIFY = 2,
+ GNSS_SV_STATE_BIT_EDGE = 3,
+ GNSS_SV_STATE_VERIFY_TRACK = 4,
+ GNSS_SV_STATE_TRACK = 5,
+ GNSS_SV_STATE_RESTART = 6,
+ GNSS_SV_STATE_DPO_TRACK = 7
+} Gnss_LocSVStateEnumType;
+
+typedef enum
+{
+ GNSS_LOC_SVINFO_MASK_HAS_EPHEMERIS = 0x01,
+ /**< Ephemeris is available for this SV */
+ GNSS_LOC_SVINFO_MASK_HAS_ALMANAC = 0x02
+ /**< Almanac is available for this SV */
+}Gnss_LocSvInfoMaskT;
+
+typedef enum
+{
+ GNSS_LOC_SV_SRCH_STATUS_IDLE = 1,
+ /**< SV is not being actively processed */
+ GNSS_LOC_SV_SRCH_STATUS_SEARCH = 2,
+ /**< The system is searching for this SV */
+ GNSS_LOC_SV_SRCH_STATUS_TRACK = 3
+ /**< SV is being tracked */
+}Gnss_LocSvSearchStatusEnumT;
+
+typedef uint32_t LocSvDgnssMeasStatusMask;
+#define LOC_MASK_DGNSS_EPOCH_TIME_VALID 0x1 /**< DGNSS Epoch time is valid */
+#define LOC_MASK_DGNSS_MEAS_STATUS_PR_VALID 0x2 /**< Pseudo Range correction is valid */
+#define LOC_MASK_DGNSS_MEAS_STATUS_PRR_VALID 0x4 /**< Pseudo Range rate correction is valid */
+
+typedef struct {
+ LocSvDgnssMeasStatusMask dgnssMeasStatus;
+ /**< Bitmask indicating the DGNSS SV measurement status. */
+
+ uint32_t diffDataEpochTimeMsec;
+ /**< Age of differential data in Milli Seconds with respect to the Measurement time. */
+
+ float prCorrMeters;
+ /**< Pseudo Range correction in meters. */
+
+ float prrCorrMetersPerSec;
+ /**< Pseudo Range rate correction in meters per second. */
+} Gnss_LocDgnssSVMeasurement;
+
+typedef struct
+{
+ uint32_t size;
+ Gnss_LocSvSystemEnumType gnssSystem;
+ // 0 signal type mask indicates invalid value
+ GnssSignalTypeMask gnssSignalTypeMask;
+ uint16_t gnssSvId;
+ /** Unique SV Identifier.
+ * For SV Range of supported constellation, please refer to the
+ * comment section of gnssSvId in GpsMeasUsageInfo.
+ */
+ uint8_t gloFrequency;
+ /**< GLONASS frequency number + 7 \n
+ Valid only for GLONASS System \n
+ Shall be ignored for all other systems \n
+ - Range: 1 to 14 \n
+ */
+ Gnss_LocSvSearchStatusEnumT svStatus;
+ /**< Satellite search state \n
+ @ENUM()
+ */
+ bool healthStatus_valid;
+ /**< SV Health Status validity flag\n
+ - 0: Not valid \n
+ - 1: Valid \n
+ */
+ uint8_t healthStatus;
+ /**< Health status.
+ \begin{itemize1}
+ \item Range: 0 to 1; 0 = unhealthy, \n 1 = healthy, 2 = unknown
+ \vspace{-0.18in} \end{itemize1}
+ */
+ Gnss_LocSvInfoMaskT svInfoMask;
+ /**< Indicates whether almanac and ephemeris information is available. \n
+ @MASK()
+ */
+ uint64_t measurementStatus;
+ /**< Bitmask indicating SV measurement status.
+ Valid bitmasks: \n
+ If any MSB bit in 0xFFC0000000000000 DONT_USE is set, the measurement
+ must not be used by the client.
+ @MASK()
+ */
+ uint16_t CNo;
+ /**< Carrier to Noise ratio \n
+ - Units: 0.1 dBHz \n
+ */
+ uint16_t gloRfLoss;
+ /**< GLONASS Rf loss reference to Antenna. \n
+ - Units: dB, Scale: 0.1 \n
+ */
+ bool lossOfLock;
+ /**< Loss of signal lock indicator \n
+ - 0: Signal in continuous track \n
+ - 1: Signal not in track \n
+ */
+ int16_t measLatency;
+ /**< Age of the measurement. Positive value means measurement precedes ref time. \n
+ - Units: msec \n
+ */
+ Gnss_LocSVTimeSpeedStructType svTimeSpeed;
+ /**< Unfiltered SV Time and Speed information
+ */
+ float dopplerAccel;
+ /**< Satellite Doppler Accelertion\n
+ - Units: Hz/s \n
+ */
+ bool multipathEstValid;
+ /**< Multipath estimate validity flag\n
+ - 0: Multipath estimate not valid \n
+ - 1: Multipath estimate valid \n
+ */
+ float multipathEstimate;
+ /**< Estimate of multipath in measurement\n
+ - Units: Meters \n
+ */
+ bool fineSpeedValid;
+ /**< Fine speed validity flag\n
+ - 0: Fine speed not valid \n
+ - 1: Fine speed valid \n
+ */
+ float fineSpeed;
+ /**< Carrier phase derived speed \n
+ - Units: m/s \n
+ */
+ bool fineSpeedUncValid;
+ /**< Fine speed uncertainty validity flag\n
+ - 0: Fine speed uncertainty not valid \n
+ - 1: Fine speed uncertainty valid \n
+ */
+ float fineSpeedUnc;
+ /**< Carrier phase derived speed \n
+ - Units: m/s \n
+ */
+ bool carrierPhaseValid;
+ /**< Carrier Phase measurement validity flag\n
+ - 0: Carrier Phase not valid \n
+ - 1: Carrier Phase valid \n
+ */
+ double carrierPhase;
+ /**< Carrier phase measurement [L1 cycles] \n
+ */
+ bool cycleSlipCountValid;
+ /**< Cycle slup count validity flag\n
+ - 0: Not valid \n
+ - 1: Valid \n
+ */
+ uint8_t cycleSlipCount;
+ /**< Increments when a CSlip is detected */
+
+ bool svDirectionValid;
+ /**< Validity flag for SV direction */
+
+ float svAzimuth;
+ /**< Satellite Azimuth
+ - Units: radians \n
+ */
+ float svElevation;
+ /**< Satellite Elevation
+ - Units: radians \n
+ */
+ uint64_t validMeasStatusMask;
+ /**< Bitmask indicating SV measurement status Validity.
+ Valid bitmasks: \n
+ If any MSB bit in 0xFFC0000000000000 DONT_USE is set, the measurement
+ must not be used by the client.
+ @MASK()
+ */
+ bool carrierPhaseUncValid;
+ /**< Validity flag for SV direction */
+
+ float carrierPhaseUnc;
+
+ /** < DGNSS Measurements Report for SVs */
+ Gnss_LocDgnssSVMeasurement dgnssSvMeas;
+} Gnss_SVMeasurementStructType;
+
+
+typedef uint64_t GpsSvMeasHeaderFlags;
+#define GNSS_SV_MEAS_HEADER_HAS_LEAP_SECOND 0x000000001
+#define GNSS_SV_MEAS_HEADER_HAS_CLOCK_FREQ 0x000000002
+#define GNSS_SV_MEAS_HEADER_HAS_AP_TIMESTAMP 0x000000004
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_GLO_INTER_SYSTEM_BIAS 0x000000008
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_BDS_INTER_SYSTEM_BIAS 0x000000010
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_GAL_INTER_SYSTEM_BIAS 0x000000020
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_GLO_INTER_SYSTEM_BIAS 0x000000040
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_GLO_INTER_SYSTEM_BIAS 0x000000080
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_BDS_INTER_SYSTEM_BIAS 0x000000100
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME 0x000000200
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME 0x000000400
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME 0x000000800
+#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME 0x000001000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME 0x000002000
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_SYSTEM_TIME_EXT 0x000004000
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_SYSTEM_TIME_EXT 0x000008000
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_SYSTEM_TIME_EXT 0x000010000
+#define GNSS_SV_MEAS_HEADER_HAS_QZSS_SYSTEM_TIME_EXT 0x000020000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_SYSTEM_TIME_EXT 0x000040000
+#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L5_TIME_BIAS 0x000080000
+#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5A_TIME_BIAS 0x000100000
+#define GNSS_SV_MEAS_HEADER_HAS_BDSB1IB2A_TIME_BIAS 0x000200000
+#define GNSS_SV_MEAS_HEADER_HAS_GPS_NAVIC_INTER_SYSTEM_BIAS 0x000400000
+#define GNSS_SV_MEAS_HEADER_HAS_GAL_NAVIC_INTER_SYSTEM_BIAS 0x000800000
+#define GNSS_SV_MEAS_HEADER_HAS_GLO_NAVIC_INTER_SYSTEM_BIAS 0x001000000
+#define GNSS_SV_MEAS_HEADER_HAS_BDS_NAVIC_INTER_SYSTEM_BIAS 0x002000000
+#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME 0x004000000
+#define GNSS_SV_MEAS_HEADER_HAS_NAVIC_SYSTEM_TIME_EXT 0x008000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_TYPE 0x010000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_CORRECTION_SOURCE_ID 0x020000000
+#define GNSS_SV_MEAS_HEADER_HAS_DGNSS_REF_STATION_ID 0x040000000
+#define GNSS_SV_MEAS_HEADER_HAS_REF_COUNT_TICKS 0x080000000
+#define GNSS_SV_MEAS_HEADER_HAS_GPSL1L2C_TIME_BIAS 0x100000000
+#define GNSS_SV_MEAS_HEADER_HAS_GLOG1G2_TIME_BIAS 0x200000000
+#define GNSS_SV_MEAS_HEADER_HAS_BDSB1IB1C_TIME_BIAS 0x400000000
+#define GNSS_SV_MEAS_HEADER_HAS_GALE1E5B_TIME_BIAS 0x800000000
+
+typedef struct
+{
+ uint32_t size;
+ // see defines in GNSS_SV_MEAS_HEADER_HAS_XXX_XXX
+ uint64_t flags;
+
+ Gnss_LeapSecondInfoStructType leapSec;
+
+ Gnss_LocRcvrClockFrequencyInfoStructType clockFreq; /* Freq */
+
+ Gnss_ApTimeStampStructType apBootTimeStamp;
+
+ Gnss_InterSystemBiasStructType gpsGloInterSystemBias;
+ Gnss_InterSystemBiasStructType gpsBdsInterSystemBias;
+ Gnss_InterSystemBiasStructType gpsGalInterSystemBias;
+ Gnss_InterSystemBiasStructType bdsGloInterSystemBias;
+ Gnss_InterSystemBiasStructType galGloInterSystemBias;
+ Gnss_InterSystemBiasStructType galBdsInterSystemBias;
+ Gnss_InterSystemBiasStructType gpsNavicInterSystemBias;
+ Gnss_InterSystemBiasStructType galNavicInterSystemBias;
+ Gnss_InterSystemBiasStructType gloNavicInterSystemBias;
+ Gnss_InterSystemBiasStructType bdsNavicInterSystemBias;
+ Gnss_InterSystemBiasStructType gpsL1L5TimeBias;
+ Gnss_InterSystemBiasStructType galE1E5aTimeBias;
+ Gnss_InterSystemBiasStructType bdsB1iB2aTimeBias;
+ Gnss_InterSystemBiasStructType gpsL1L2cTimeBias;
+ Gnss_InterSystemBiasStructType gloG1G2TimeBias;
+ Gnss_InterSystemBiasStructType bdsB1iB1cTimeBias;
+ Gnss_InterSystemBiasStructType galE1E5bTimeBias;
+
+ GnssSystemTimeStructType gpsSystemTime;
+ GnssSystemTimeStructType galSystemTime;
+ GnssSystemTimeStructType bdsSystemTime;
+ GnssSystemTimeStructType qzssSystemTime;
+ GnssSystemTimeStructType navicSystemTime;
+ GnssGloTimeStructType gloSystemTime;
+
+ /** GPS system RTC time information. */
+ Gnss_LocGnssTimeExtStructType gpsSystemTimeExt;
+ /** GAL system RTC time information. */
+ Gnss_LocGnssTimeExtStructType galSystemTimeExt;
+ /** BDS system RTC time information. */
+ Gnss_LocGnssTimeExtStructType bdsSystemTimeExt;
+ /** QZSS system RTC time information. */
+ Gnss_LocGnssTimeExtStructType qzssSystemTimeExt;
+ /** GLONASS system RTC time information. */
+ Gnss_LocGnssTimeExtStructType gloSystemTimeExt;
+ /** NAVIC system RTC time information. */
+ Gnss_LocGnssTimeExtStructType navicSystemTimeExt;
+
+ /** Receiver tick at frame count */
+ uint64_t refCountTicks;
+
+ /** DGNSS corrections source type RTCM, 3GPP etc, if DGNSS was
+ * used for these measurements. */
+ LocDgnssCorrectionSourceType dgnssCorrectionSourceType;
+
+ /** DGNSS SourceID: 32bit number identifying the DGNSS source
+ * ID, if DGNSS was used for these measurements. */
+ uint32_t dgnssCorrectionSourceID;
+
+ /** DGNSS Ref station ID: 32bit number identifying the DGNSS
+ * ref station ID, if DGNSS was used for these measurements. */
+ uint16_t dgnssRefStationId;
+} GnssSvMeasurementHeader;
+
+typedef struct {
+ uint32_t size;
+ bool isNhz;
+ GnssSvMeasurementHeader svMeasSetHeader;
+ uint32_t svMeasCount;
+ Gnss_SVMeasurementStructType svMeas[GNSS_LOC_SV_MEAS_LIST_MAX_SIZE];
+
+} GnssSvMeasurementSet;
+
+typedef struct {
+ uint32_t size; // set to sizeof(GnssMeasurements)
+ GnssSvMeasurementSet gnssSvMeasurementSet;
+ GnssMeasurementsNotification gnssMeasNotification;
+} GnssMeasurements;
+
+typedef enum
+{
+ GNSS_SV_POLY_COEFF_VALID = 0x01,
+ /**< SV position in orbit coefficients are valid */
+ GNSS_SV_POLY_IONO_VALID = 0x02,
+ /**< Iono estimates are valid */
+
+ GNSS_SV_POLY_TROPO_VALID = 0x04,
+ /**< Tropo estimates are valid */
+
+ GNSS_SV_POLY_ELEV_VALID = 0x08,
+ /**< Elevation, rate, uncertainty are valid */
+
+ GNSS_SV_POLY_SRC_ALM_CORR = 0x10,
+ /**< Polynomials based on XTRA */
+
+ GNSS_SV_POLY_SBAS_IONO_VALID = 0x20,
+ /**< SBAS IONO and rate are valid */
+
+ GNSS_SV_POLY_GLO_STR4 = 0x40
+ /**< GLONASS String 4 has been received */
+} Gnss_SvPolyStatusMaskType;
+
+typedef struct {
+ uint32_t size;
+ uint16_t gnssSvId;
+ /** Unique SV Identifier.
+ * For SV Range of supported constellation, please refer to the
+ * comment section of gnssSvId in GpsMeasUsageInfo.
+ */
+ int8_t freqNum;
+ /** Freq index, only valid if u_SysInd is GLO */
+
+ GnssSvPolyStatusMaskValidity svPolyStatusMaskValidity;
+ GnssSvPolyStatusMask svPolyStatusMask;
+
+ uint32_t is_valid;
+
+ uint16_t iode;
+ /* Ephemeris reference time
+ GPS:Issue of Data Ephemeris used [unitless].
+ GLO: Tb 7-bit, refer to ICD02
+ */
+ double T0;
+ /* Reference time for polynominal calculations
+ GPS: Secs in week.
+ GLO: Full secs since Jan/01/96
+ */
+ double polyCoeffXYZ0[GNSS_SV_POLY_XYZ_0_TH_ORDER_COEFF_MAX_SIZE];
+ /* C0X, C0Y, C0Z */
+ double polyCoefXYZN[GNSS_SV_POLY_XYZ_N_TH_ORDER_COEFF_MAX_SIZE];
+ /* C1X, C2X ... C2Z, C3Z */
+ float polyCoefOther[GNSS_SV_POLY_SV_CLKBIAS_COEFF_MAX_SIZE];
+ /* C0T, C1T, C2T, C3T */
+ float svPosUnc; /* SV position uncertainty [m]. */
+ float ionoDelay; /* Ionospheric delay at d_T0 [m]. */
+ float ionoDot; /* Iono delay rate [m/s]. */
+ float sbasIonoDelay;/* SBAS Ionospheric delay at d_T0 [m]. */
+ float sbasIonoDot; /* SBAS Iono delay rate [m/s]. */
+ float tropoDelay; /* Tropospheric delay [m]. */
+ float elevation; /* Elevation [rad] at d_T0 */
+ float elevationDot; /* Elevation rate [rad/s] */
+ float elevationUnc; /* SV elevation [rad] uncertainty */
+ double velCoef[GNSS_SV_POLY_VELOCITY_COEF_MAX_SIZE];
+ /* Coefficients of velocity poly */
+ uint32_t enhancedIOD; /* Enhanced Reference Time */
+ float gpsIscL1ca;
+ float gpsIscL2c;
+ float gpsIscL5I5;
+ float gpsIscL5Q5;
+ float gpsTgd;
+ float gloTgdG1G2;
+ float bdsTgdB1;
+ float bdsTgdB2;
+ float bdsTgdB2a;
+ float bdsIscB2a;
+ float galBgdE1E5a;
+ float galBgdE1E5b;
+ float navicTgdL5;
+} GnssSvPolynomial;
+
+typedef enum {
+ GNSS_EPH_ACTION_UPDATE_SRC_UNKNOWN_V02 = 0, /**<Update ephemeris. Source of ephemeris is unknown */
+ GNSS_EPH_ACTION_UPDATE_SRC_OTA_V02 = 1, /**<Update ephemeris. Source of ephemeris is OTA */
+ GNSS_EPH_ACTION_UPDATE_SRC_NETWORK_V02 = 2, /**<Update ephemeris. Source of ephemeris is Network */
+ GNSS_EPH_ACTION_UPDATE_MAX_V02 = 999, /**<Max value for update ephemeris action. DO NOT USE */
+ GNSS_EPH_ACTION_DELETE_SRC_UNKNOWN_V02 = 1000, /**<Delete previous ephemeris from unknown source */
+ GNSS_EPH_ACTION_DELETE_SRC_NETWORK_V02 = 1001, /**<Delete previous ephemeris from network */
+ GNSS_EPH_ACTION_DELETE_SRC_OTA_V02 = 1002, /**<Delete previous ephemeris from OTA */
+ GNSS_EPH_ACTION_DELETE_MAX_V02 = 1999, /**<Max value for delete ephemeris action. DO NOT USE */
+} GnssEphAction;
+
+typedef enum {
+ GAL_EPH_SIGNAL_SRC_UNKNOWN_V02 = 0, /**< GALILEO signal is unknown */
+ GAL_EPH_SIGNAL_SRC_E1B_V02 = 1, /**< GALILEO signal is E1B */
+ GAL_EPH_SIGNAL_SRC_E5A_V02 = 2, /**< GALILEO signal is E5A */
+ GAL_EPH_SIGNAL_SRC_E5B_V02 = 3, /**< GALILEO signal is E5B */
+} GalEphSignalSource;
+
+typedef struct {
+ uint16_t gnssSvId;
+ /** Unique SV Identifier.
+ * For SV Range of supported constellation, please refer to the
+ * comment section of gnssSvId in GpsMeasUsageInfo.
+ */
+
+ GnssEphAction updateAction;
+ /**< Specifies the action and source of ephemeris. \n
+ - Type: int32 enum */
+
+ uint16_t IODE;
+ /**< Issue of data ephemeris used (unit-less). \n
+ GPS: IODE 8 bits.\n
+ BDS: AODE 5 bits. \n
+ GAL: SIS IOD 10 bits. \n
+ - Type: uint16
+ - Units: Unit-less */
+
+ double aSqrt;
+ /**< Square root of semi-major axis. \n
+ - Type: double
+ - Units: Square Root of Meters */
+
+ double deltaN;
+ /**< Mean motion difference from computed value. \n
+ - Type: double
+ - Units: Radians/Second */
+
+ double m0;
+ /**< Mean anomaly at reference time. \n
+ - Type: double
+ - Units: Radians */
+
+ double eccentricity;
+ /**< Eccentricity . \n
+ - Type: double
+ - Units: Unit-less */
+
+ double omega0;
+ /**< Longitude of ascending node of orbital plane at the weekly epoch. \n
+ - Type: double
+ - Units: Radians */
+
+ double i0;
+ /**< Inclination angle at reference time. \n
+ - Type: double
+ - Units: Radians */
+
+ double omega;
+ /**< Argument of Perigee. \n
+ - Type: double
+ - Units: Radians */
+
+ double omegaDot;
+ /**< Rate of change of right ascension. \n
+ - Type: double
+ - Units: Radians/Second */
+
+ double iDot;
+ /**< Rate of change of inclination angle. \n
+ - Type: double
+ - Units: Radians/Second */
+
+ double cUc;
+ /**< Amplitude of the cosine harmonic correction term to the argument of latitude. \n
+ - Type: double
+ - Units: Radians */
+
+ double cUs;
+ /**< Amplitude of the sine harmonic correction term to the argument of latitude. \n
+ - Type: double
+ - Units: Radians */
+
+ double cRc;
+ /**< Amplitude of the cosine harmonic correction term to the orbit radius. \n
+ - Type: double
+ - Units: Meters */
+
+ double cRs;
+ /**< Amplitude of the sine harmonic correction term to the orbit radius. \n
+ - Type: double
+ - Units: Meters */
+
+ double cIc;
+ /**< Amplitude of the cosine harmonic correction term to the angle of inclination. \n
+ - Type: double
+ - Units: Radians */
+
+ double cIs;
+ /**< Amplitude of the sine harmonic correction term to the angle of inclination. \n
+ - Type: double
+ - Units: Radians */
+
+ uint32_t toe;
+ /**< Reference time of ephemeris. \n
+ - Type: uint32
+ - Units: Seconds */
+
+ uint32_t toc;
+ /**< Clock data reference time of week. \n
+ - Type: uint32
+ - Units: Seconds */
+
+ double af0;
+ /**< Clock bias correction coefficient. \n
+ - Type: double
+ - Units: Seconds */
+
+ double af1;
+ /**< Clock drift coefficient. \n
+ - Type: double
+ - Units: Seconds/Second */
+
+ double af2;
+ /**< Clock drift rate correction coefficient. \n
+ - Type: double
+ - Units: Seconds/Seconds^2 */
+
+} GnssEphCommon;
+
+/* GPS Navigation Model Info */
+typedef struct {
+ GnssEphCommon commonEphemerisData;
+ /**< Common ephemeris data. */
+
+ uint8_t signalHealth;
+ /**< Signal health. \n
+ Bit 0 : L5 Signal Health. \n
+ Bit 1 : L2 Signal Health. \n
+ Bit 2 : L1 Signal Health. \n
+ - Type: uint8
+ - Values: 3 bit mask of signal health, where set bit indicates unhealthy signal */
+
+ uint8_t URAI;
+ /**< User Range Accuracy Index. \n
+ - Type: uint8
+ - Units: Unit-less */
+
+ uint8_t codeL2;
+ /**< Indicates which codes are commanded ON for the L2 channel (2-bits). \n
+ - Type: uint8
+ Valid Values: \n
+ - 00 : Reserved
+ - 01 : P code ON
+ - 10 : C/A code ON */
+
+ uint8_t dataFlagL2P;
+ /**< L2 P-code indication flag. \n
+ - Type: uint8
+ - Value 1 indicates that the Nav data stream was commanded OFF on the P-code of the L2 channel. */
+
+ double tgd;
+ /**< Time of group delay. \n
+ - Type: double
+ - Units: Seconds */
+
+ uint8_t fitInterval;
+ /**< Indicates the curve-fit interval used by the CS. \n
+ - Type: uint8
+ Valid Values:
+ - 0 : Four hours
+ - 1 : Greater than four hours */
+
+ uint16_t IODC;
+ /**< Issue of Data, Clock. \n
+ - Type: uint16
+ - Units: Unit-less */
+} GpsEphemeris;
+
+/* GLONASS Navigation Model Info */
+typedef struct {
+
+ uint16_t gnssSvId;
+ /**< GNSS SV ID.
+ - Type: uint16
+ - Range: 65 to 96 if known. When the slot number to SV ID mapping is unknown, set to 255 */
+
+ GnssEphAction updateAction;
+ /**< Specifies the action and source of ephemeris. \n
+ - Type: int32 enum */
+
+ uint8_t bnHealth;
+ /**< SV health flags. \n
+ - Type: uint8
+ Valid Values: \n
+ - 0 : Healthy
+ - 1 : Unhealthy */
+
+ uint8_t lnHealth;
+ /**< Ln SV health flags. GLONASS-M. \n
+ - Type: uint8
+ Valid Values: \n
+ - 0 : Healthy
+ - 1 : Unhealthy */
+
+ uint8_t tb;
+ /**< Index of a time interval within current day according to UTC(SU) + 03 hours 00 min. \n
+ - Type: uint8
+ - Units: Unit-less */
+
+ uint8_t ft;
+ /**< SV accuracy index. \n
+ - Type: uint8
+ - Units: Unit-less */
+
+ uint8_t gloM;
+ /**< GLONASS-M flag. \n
+ - Type: uint8
+ Valid Values: \n
+ - 0 : GLONASS
+ - 1 : GLONASS-M */
+
+ uint8_t enAge;
+ /**< Characterizes "Age" of current information. \n
+ - Type: uint8
+ - Units: Days */
+
+ uint8_t gloFrequency;
+ /**< GLONASS frequency number + 8. \n
+ - Type: uint8
+ - Range: 1 to 14
+ */
+
+ uint8_t p1;
+ /**< Time interval between two adjacent values of tb parameter. \n
+ - Type: uint8
+ - Units: Minutes */
+
+ uint8_t p2;
+ /**< Flag of oddness ("1") or evenness ("0") of the value of tb \n
+ for intervals 30 or 60 minutes. \n
+ - Type: uint8 */
+
+ float deltaTau;
+ /**< Time difference between navigation RF signal transmitted in L2 sub-band \n
+ and aviation RF signal transmitted in L1 sub-band. \n
+ - Type: floating point
+ - Units: Seconds */
+
+ double position[3];
+ /**< Satellite XYZ position. \n
+ - Type: array of doubles
+ - Units: Meters */
+
+ double velocity[3];
+ /**< Satellite XYZ velocity. \n
+ - Type: array of doubles
+ - Units: Meters/Second */
+
+ double acceleration[3];
+ /**< Satellite XYZ sola-luni acceleration. \n
+ - Type: array of doubles
+ - Units: Meters/Second^2 */
+
+ float tauN;
+ /**< Satellite clock correction relative to GLONASS time. \n
+ - Type: floating point
+ - Units: Seconds */
+
+ float gamma;
+ /**< Relative deviation of predicted carrier frequency value \n
+ from nominal value at the instant tb. \n
+ - Type: floating point
+ - Units: Unit-less */
+
+ double toe;
+ /**< Complete ephemeris time, including N4, NT and Tb. \n
+ [(N4-1)*1461 + (NT-1)]*86400 + tb*900 \n
+ - Type: double
+ - Units: Seconds */
+
+ uint16_t nt;
+ /**< Current date, calendar number of day within four-year interval. \n
+ Starting from the 1-st of January in a leap year. \n
+ - Type: uint16
+ - Units: Days */
+} GlonassEphemeris;
+
+/* BDS Navigation Model Info */
+typedef struct {
+
+ GnssEphCommon commonEphemerisData;
+ /**< Common ephemeris data. */
+
+ uint8_t svHealth;
+ /**< Satellite health information applied to both B1 and B2 (SatH1). \n
+ - Type: uint8
+ Valid Values: \n
+ - 0 : Healthy
+ - 1 : Unhealthy */
+
+ uint8_t AODC;
+ /**< Age of data clock. \n
+ - Type: uint8
+ - Units: Hours */
+
+ double tgd1;
+ /**< Equipment group delay differential on B1 signal. \n
+ - Type: double
+ - Units: Nano-Seconds */
+
+ double tgd2;
+ /**< Equipment group delay differential on B2 signal. \n
+ - Type: double
+ - Units: Nano-Seconds */
+
+ uint8_t URAI;
+ /**< User range accuracy index (4-bits). \n
+ - Type: uint8
+ - Units: Unit-less */
+} BdsEphemeris;
+
+/* GALIELO Navigation Model Info */
+typedef struct {
+
+ GnssEphCommon commonEphemerisData;
+ /**< Common ephemeris data. */
+
+ GalEphSignalSource dataSourceSignal;
+ /**< Galileo Signal Source. \n
+ Valid Values: \n
+ - GAL_EPH_SIGNAL_SRC_UNKNOWN (0) -- GALILEO signal is unknown
+ - GAL_EPH_SIGNAL_SRC_E1B (1) -- GALILEO signal is E1B
+ - GAL_EPH_SIGNAL_SRC_E5A (2) -- GALILEO signal is E5A
+ - GAL_EPH_SIGNAL_SRC_E5B (3) -- GALILEO signal is E5B */
+
+ uint8_t sisIndex;
+ /**< Signal-in-space index for dual frequency E1-E5b/E5a depending on dataSignalSource. \n
+ - Type: uint8
+ - Units: Unit-less */
+
+ double bgdE1E5a;
+ /**< E1-E5a Broadcast group delay from F/Nav (E5A). \n
+ - Type: double
+ - Units: Seconds */
+
+ double bgdE1E5b;
+ /**< E1-E5b Broadcast group delay from I/Nav (E1B or E5B). \n
+ For E1B or E5B signal, both bgdE1E5a and bgdE1E5b are valid. \n
+ For E5A signal, only bgdE1E5a is valid. \n
+ Signal source identified using dataSignalSource. \n
+ - Type: double
+ - Units: Seconds */
+
+ uint8_t svHealth;
+ /**< SV health status of signal identified by dataSourceSignal. \n
+ - Type: uint8
+ Valid Values: \n
+ - 0 : Healthy
+ - 1 : Unhealthy */
+} GalileoEphemeris;
+
+/** GPS Navigation model for each SV */
+typedef struct {
+ uint16_t numOfEphemeris;
+ GpsEphemeris gpsEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02];
+} GpsEphemerisResponse;
+
+/** GLONASS Navigation model for each SV */
+typedef struct {
+ uint16_t numOfEphemeris;
+ GlonassEphemeris gloEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02];
+} GlonassEphemerisResponse;
+
+/** BDS Navigation model for each SV */
+typedef struct {
+ uint16_t numOfEphemeris;
+ BdsEphemeris bdsEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02];
+} BdsEphemerisResponse;
+
+/** GALILEO Navigation model for each SV */
+typedef struct {
+ uint16_t numOfEphemeris;
+ GalileoEphemeris galEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02];
+} GalileoEphemerisResponse;
+
+/** QZSS Navigation model for each SV */
+typedef struct {
+ uint16_t numOfEphemeris;
+ GpsEphemeris qzssEphemerisData[GNSS_EPHEMERIS_LIST_MAX_SIZE_V02];
+} QzssEphemerisResponse;
+
+
+typedef struct {
+ /** Indicates GNSS Constellation Type
+ Mandatory field */
+ Gnss_LocSvSystemEnumType gnssConstellation;
+
+ /** GPS System Time of the ephemeris report */
+ bool isSystemTimeValid;
+ GnssSystemTimeStructType systemTime;
+
+ union {
+ /** GPS Ephemeris */
+ GpsEphemerisResponse gpsEphemeris;
+ /** GLONASS Ephemeris */
+ GlonassEphemerisResponse glonassEphemeris;
+ /** BDS Ephemeris */
+ BdsEphemerisResponse bdsEphemeris;
+ /** GALILEO Ephemeris */
+ GalileoEphemerisResponse galileoEphemeris;
+ /** QZSS Ephemeris */
+ QzssEphemerisResponse qzssEphemeris;
+ } ephInfo;
+} GnssSvEphemerisReport;
+
+typedef struct {
+ /** GPS System Time of the iono model report */
+ bool isSystemTimeValid;
+ GnssSystemTimeStructType systemTime;
+
+ /** Indicates GNSS Constellation Type */
+ Gnss_LocSvSystemEnumType gnssConstellation;
+
+ float alpha0;
+ /**< Klobuchar Model Parameter Alpha 0.
+ - Type: float
+ - Unit: Seconds
+ */
+
+ float alpha1;
+ /**< Klobuchar Model Parameter Alpha 1.
+ - Type: float
+ - Unit: Seconds / Semi-Circle
+ */
+
+ float alpha2;
+ /**< Klobuchar Model Parameter Alpha 2.
+ - Type: float
+ - Unit: Seconds / Semi-Circle^2
+ */
+
+ float alpha3;
+ /**< Klobuchar Model Parameter Alpha 3.
+ - Type: float
+ - Unit: Seconds / Semi-Circle^3
+ */
+
+ float beta0;
+ /**< Klobuchar Model Parameter Beta 0.
+ - Type: float
+ - Unit: Seconds
+ */
+
+ float beta1;
+ /**< Klobuchar Model Parameter Beta 1.
+ - Type: float
+ - Unit: Seconds / Semi-Circle
+ */
+
+ float beta2;
+ /**< Klobuchar Model Parameter Beta 2.
+ - Type: float
+ - Unit: Seconds / Semi-Circle^2
+ */
+
+ float beta3;
+ /**< Klobuchar Model Parameter Beta 3.
+ - Type: float
+ - Unit: Seconds / Semi-Circle^3
+ */
+} GnssKlobucharIonoModel;
+
+typedef struct {
+ /** GPS System Time of the report */
+ bool isSystemTimeValid;
+ GnssSystemTimeStructType systemTime;
+
+ GnssAdditionalSystemInfoMask validityMask;
+ double tauC;
+ int8_t leapSec;
+} GnssAdditionalSystemInfo;
+
+/* Various Short Range Node Technology type*/
+typedef enum {
+ SRN_AP_DATA_TECH_TYPE_NONE,
+ SRN_AP_DATA_TECH_TYPE_BT,
+ SRN_AP_DATA_TECH_TYPE_BTLE,
+ SRN_AP_DATA_TECH_TYPE_NFC,
+ SRN_AP_DATA_TECH_TYPE_MOBILE_CODE,
+ SRN_AP_DATA_TECH_TYPE_OTHER
+} Gnss_SrnTech;
+
+/* Mac Address type requested by modem */
+typedef enum {
+ SRN_AP_DATA_PUBLIC_MAC_ADDR_TYPE_INVALID, /* No valid mac address type send */
+ SRN_AP_DATA_PUBLIC_MAC_ADDR_TYPE_PUBLIC, /* SRN AP MAC Address type PUBLIC */
+ SRN_AP_DATA_PUBLIC_MAC_ADDR_TYPE_PRIVATE, /* SRN AP MAC Address type PRIVATE */
+ SRN_AP_DATA_PUBLIC_MAC_ADDR_TYPE_OTHER, /* SRN AP MAC Address type OTHER */
+}Gnss_Srn_MacAddr_Type;
+
+typedef struct
+{
+ uint32_t size;
+ Gnss_SrnTech srnTechType; /* SRN Technology type in request */
+ bool srnRequest; /* scan - start(true) or stop(false) */
+ bool e911Mode; /* If in E911 emergency */
+ Gnss_Srn_MacAddr_Type macAddrType; /* SRN AP MAC Address type */
+} GnssSrnDataReq;
+
+/* Provides the current GNSS SV Type configuration to the client.
+ * This is fetched via direct call to GNSS Adapter bypassing
+ * Location API */
+typedef std::function<void(
+ const GnssSvTypeConfig& config
+)> GnssSvTypeConfigCallback;
+
+/*
+ * Represents the status of AGNSS augmented to support IPv4.
+ */
+struct AGnssExtStatusIpV4 {
+ AGpsExtType type;
+ LocApnTypeMask apnTypeMask;
+ LocAGpsStatusValue status;
+ /*
+ * 32-bit IPv4 address.
+ */
+ uint32_t ipV4Addr;
+};
+
+/*
+ * Represents the status of AGNSS augmented to support IPv6.
+ */
+struct AGnssExtStatusIpV6 {
+ AGpsExtType type;
+ LocApnTypeMask apnTypeMask;
+ LocAGpsStatusValue status;
+ /*
+ * 128-bit IPv6 address.
+ */
+ uint8_t ipV6Addr[16];
+};
+
+/*
+* Represents the the Nfw Notification structure
+*/
+#define GNSS_MAX_NFW_APP_STRING_LEN 64
+#define GNSS_MAX_NFW_STRING_LEN 20
+
+typedef enum {
+ GNSS_NFW_CTRL_PLANE = 0,
+ GNSS_NFW_SUPL = 1,
+ GNSS_NFW_IMS = 10,
+ GNSS_NFW_SIM = 11,
+ GNSS_NFW_OTHER_PROTOCOL_STACK = 100
+} GnssNfwProtocolStack;
+
+typedef enum {
+ GNSS_NFW_CARRIER = 0,
+ GNSS_NFW_OEM = 10,
+ GNSS_NFW_MODEM_CHIPSET_VENDOR = 11,
+ GNSS_NFW_GNSS_CHIPSET_VENDOR = 12,
+ GNSS_NFW_OTHER_CHIPSET_VENDOR = 13,
+ GNSS_NFW_AUTOMOBILE_CLIENT = 20,
+ GNSS_NFW_OTHER_REQUESTOR = 100
+} GnssNfwRequestor;
+
+typedef enum {
+ GNSS_NFW_REJECTED = 0,
+ GNSS_NFW_ACCEPTED_NO_LOCATION_PROVIDED = 1,
+ GNSS_NFW_ACCEPTED_LOCATION_PROVIDED = 2,
+} GnssNfwResponseType;
+
+typedef struct {
+ char proxyAppPackageName[GNSS_MAX_NFW_APP_STRING_LEN];
+ GnssNfwProtocolStack protocolStack;
+ char otherProtocolStackName[GNSS_MAX_NFW_STRING_LEN];
+ GnssNfwRequestor requestor;
+ char requestorId[GNSS_MAX_NFW_STRING_LEN];
+ GnssNfwResponseType responseType;
+ bool inEmergencyMode;
+ bool isCachedLocation;
+} GnssNfwNotification;
+
+typedef uint16_t GnssMeasurementCorrectionsCapabilitiesMask;
+typedef enum {
+ GNSS_MEAS_CORR_LOS_SATS = 1 << 0,
+ GNSS_MEAS_CORR_EXCESS_PATH_LENGTH = 1 << 1,
+ GNSS_MEAS_CORR_REFLECTING_PLANE = 1 << 2,
+} GnssMeasurementCorrectionsCapabilities;
+
+/* Represents GNSS NMEA Report Rate Configuration */
+typedef enum {
+ GNSS_NMEA_REPORT_RATE_UNKNOWN = 0,
+ GNSS_NMEA_REPORT_RATE_1HZ = 1,
+ GNSS_NMEA_REPORT_RATE_NHZ = 2
+} GnssNMEARptRate;
+
+/* ODCPI Request Info */
+enum OdcpiRequestType {
+ ODCPI_REQUEST_TYPE_START,
+ ODCPI_REQUEST_TYPE_STOP
+};
+struct OdcpiRequestInfo {
+ uint32_t size;
+ OdcpiRequestType type;
+ uint32_t tbfMillis;
+ bool isEmergencyMode;
+};
+/* Callback to send ODCPI request to framework */
+typedef std::function<void(const OdcpiRequestInfo& request)> OdcpiRequestCallback;
+
+/* ODCPI callback priorities*/
+enum OdcpiPrioritytype {
+ ODCPI_HANDLER_PRIORITY_LOW,
+ ODCPI_HANDLER_PRIORITY_HIGH
+};
+
+/*
+ * Callback with AGNSS(IpV4) status information.
+ *
+ * @param status Will be of type AGnssExtStatusIpV4.
+ */
+typedef void (*AgnssStatusIpV4Cb)(AGnssExtStatusIpV4 status);
+
+/*
+* Callback with AGNSS(IpV6) status information.
+*
+* @param status Will be of type AGnssExtStatusIpV6.
+*/
+typedef void (*AgnssStatusIpV6Cb)(AGnssExtStatusIpV6 status);
+
+/*
+* Callback with NFW information.
+*/
+typedef void(*NfwStatusCb)(GnssNfwNotification notification);
+typedef bool(*IsInEmergencySession)(void);
+
+enum AntennaInfoStatus {
+ ANTENNA_INFO_SUCCESS = 0,
+ ANTENNA_INFO_ERROR_ALREADY_INIT = 1,
+ ANTENNA_INFO_ERROR_GENERIC = 2
+};
+
+/*
+* Callback with Measurement corrections information.
+*/
+typedef void(*measCorrSetCapabilitiesCb)(GnssMeasurementCorrectionsCapabilitiesMask capabilities);
+
+/*
+ * Callback with AGNSS(IpV6) status information.
+ *
+ * @param status Will be of type AGnssExtStatusIpV6.
+ */
+typedef void (*AgnssStatusIpV6Cb)(AGnssExtStatusIpV6 status);
+
+/*
+* Callback with Antenna information.
+*/
+typedef void(*antennaInfoCb)(std::vector<GnssAntennaInformation> gnssAntennaInformations);
+
+/* Constructs for interaction with loc_net_iface library */
+typedef void (*LocAgpsOpenResultCb)(bool isSuccess, AGpsExtType agpsType, const char* apn,
+ AGpsBearerType bearerType, void* userDataPtr);
+
+typedef void (*LocAgpsCloseResultCb)(bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
+
+enum PowerStateType {
+ POWER_STATE_UNKNOWN = 0,
+ POWER_STATE_SUSPEND = 1,
+ POWER_STATE_RESUME = 2,
+ POWER_STATE_SHUTDOWN = 3
+};
+
+/* Shared resources of LocIpc */
+#define LOC_IPC_HAL "/dev/socket/location/socket_hal"
+#define LOC_IPC_XTRA "/dev/socket/location/xtra/socket_xtra"
+
+#define SOCKET_DIR_LOCATION "/dev/socket/location/"
+#define SOCKET_DIR_EHUB "/dev/socket/location/ehub/"
+#define SOCKET_TO_LOCATION_HAL_DAEMON "/dev/socket/loc_client/hal_daemon"
+
+#define SOCKET_LOC_CLIENT_DIR "/dev/socket/loc_client/"
+#define EAP_LOC_CLIENT_DIR "/data/vendor/location/extap_locclient/"
+
+#define LOC_CLIENT_NAME_PREFIX "toclient"
+// Please note that the socket name for all location hal daemon client need
+// to start with LOC_CLIENT_NAME_PREFIX so that upon hal daemon restarts,
+// every client can get the notification that hal daemon has restarted.
+#define LOC_INTAPI_NAME_PREFIX LOC_CLIENT_NAME_PREFIX "_intapi"
+
+typedef uint64_t NetworkHandle;
+#define NETWORK_HANDLE_UNKNOWN ~0
+#define MAX_NETWORK_HANDLES 10
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* GPS_EXTENDED_C_H */
diff --git a/gps/utils/linked_list.c b/gps/utils/linked_list.c
new file mode 100644
index 0000000..02e1463
--- /dev/null
+++ b/gps/utils/linked_list.c
@@ -0,0 +1,325 @@
+/* Copyright (c) 2011, 2014, 2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "LocSvc_utils_ll"
+
+#include "linked_list.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <loc_pla.h>
+#include <log_util.h>
+
+typedef struct list_element {
+ struct list_element* next;
+ struct list_element* prev;
+ void* data_ptr;
+ void (*dealloc_func)(void*);
+}list_element;
+
+typedef struct list_state {
+ list_element* p_head;
+ list_element* p_tail;
+} list_state;
+
+/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */
+
+/*===========================================================================
+
+ FUNCTION: linked_list_init
+
+ ===========================================================================*/
+linked_list_err_type linked_list_init(void** list_data)
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_PARAMETER;
+ }
+
+ list_state* tmp_list;
+ tmp_list = (list_state*)calloc(1, sizeof(list_state));
+ if( tmp_list == NULL )
+ {
+ LOC_LOGE("%s: Unable to allocate space for list!\n", __FUNCTION__);
+ return eLINKED_LIST_FAILURE_GENERAL;
+ }
+
+ tmp_list->p_head = NULL;
+ tmp_list->p_tail = NULL;
+
+ *list_data = tmp_list;
+
+ return eLINKED_LIST_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_destroy
+
+ ===========================================================================*/
+linked_list_err_type linked_list_destroy(void** list_data)
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_HANDLE;
+ }
+
+ list_state* p_list = (list_state*)*list_data;
+
+ linked_list_flush(p_list);
+
+ free(*list_data);
+ *list_data = NULL;
+
+ return eLINKED_LIST_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_add
+
+ ===========================================================================*/
+linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*))
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_HANDLE;
+ }
+
+ if( data_obj == NULL )
+ {
+ LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_PARAMETER;
+ }
+
+ list_state* p_list = (list_state*)list_data;
+ list_element* elem = (list_element*)malloc(sizeof(list_element));
+ if( elem == NULL )
+ {
+ LOC_LOGE("%s: Memory allocation failed\n", __FUNCTION__);
+ return eLINKED_LIST_FAILURE_GENERAL;
+ }
+
+ /* Copy data to newly created element */
+ elem->data_ptr = data_obj;
+ elem->next = NULL;
+ elem->prev = NULL;
+ elem->dealloc_func = dealloc;
+
+ /* Replace head element */
+ list_element* tmp = p_list->p_head;
+ p_list->p_head = elem;
+ /* Point next to the previous head element */
+ p_list->p_head->next = tmp;
+
+ if( tmp != NULL )
+ {
+ tmp->prev = p_list->p_head;
+ }
+ else
+ {
+ p_list->p_tail = p_list->p_head;
+ }
+
+ return eLINKED_LIST_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_remove
+
+ ===========================================================================*/
+linked_list_err_type linked_list_remove(void* list_data, void **data_obj)
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_HANDLE;
+ }
+
+ if( data_obj == NULL )
+ {
+ LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_PARAMETER;
+ }
+
+ list_state* p_list = (list_state*)list_data;
+ if( p_list->p_tail == NULL )
+ {
+ return eLINKED_LIST_UNAVAILABLE_RESOURCE;
+ }
+
+ list_element* tmp = p_list->p_tail;
+
+ /* Replace tail element */
+ p_list->p_tail = tmp->prev;
+
+ if( p_list->p_tail != NULL )
+ {
+ p_list->p_tail->next = NULL;
+ }
+ else
+ {
+ p_list->p_head = p_list->p_tail;
+ }
+
+ /* Copy data to output param */
+ *data_obj = tmp->data_ptr;
+
+ /* Free allocated list element */
+ free(tmp);
+
+ return eLINKED_LIST_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_empty
+
+ ===========================================================================*/
+int linked_list_empty(void* list_data)
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return (int)eLINKED_LIST_INVALID_HANDLE;
+ }
+ else
+ {
+ list_state* p_list = (list_state*)list_data;
+ return p_list->p_head == NULL ? 1 : 0;
+ }
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_flush
+
+ ===========================================================================*/
+linked_list_err_type linked_list_flush(void* list_data)
+{
+ if( list_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
+ return eLINKED_LIST_INVALID_HANDLE;
+ }
+
+ list_state* p_list = (list_state*)list_data;
+
+ /* Remove all dynamically allocated elements */
+ while( p_list->p_head != NULL )
+ {
+ list_element* tmp = p_list->p_head->next;
+
+ /* Free data pointer if told to do so. */
+ if( p_list->p_head->dealloc_func != NULL )
+ {
+ p_list->p_head->dealloc_func(p_list->p_head->data_ptr);
+ }
+
+ /* Free list element */
+ free(p_list->p_head);
+
+ p_list->p_head = tmp;
+ }
+
+ p_list->p_tail = NULL;
+
+ return eLINKED_LIST_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: linked_list_search
+
+ ===========================================================================*/
+linked_list_err_type linked_list_search(void* list_data, void **data_p,
+ bool (*equal)(void* data_0, void* data),
+ void* data_0, bool rm_if_found)
+{
+ if( list_data == NULL || NULL == equal )
+ {
+ LOC_LOGE("%s: Invalid list parameter! list_data %p equal %p\n",
+ __FUNCTION__, list_data, equal);
+ return eLINKED_LIST_INVALID_HANDLE;
+ }
+
+ list_state* p_list = (list_state*)list_data;
+ if( p_list->p_tail == NULL )
+ {
+ return eLINKED_LIST_UNAVAILABLE_RESOURCE;
+ }
+
+ list_element* tmp = p_list->p_head;
+
+ if (NULL != data_p) {
+ *data_p = NULL;
+ }
+
+ while (NULL != tmp) {
+ if ((*equal)(data_0, tmp->data_ptr)) {
+ if (NULL != data_p) {
+ *data_p = tmp->data_ptr;
+ }
+
+ if (rm_if_found) {
+ if (NULL == tmp->prev) {
+ p_list->p_head = tmp->next;
+ } else {
+ tmp->prev->next = tmp->next;
+ }
+
+ if (NULL == tmp->next) {
+ p_list->p_tail = tmp->prev;
+ } else {
+ tmp->next->prev = tmp->prev;
+ }
+
+ tmp->prev = tmp->next = NULL;
+
+ // dealloc data if it is not copied out && caller
+ // has given us a dealloc function pointer.
+ if (NULL == data_p && NULL != tmp->dealloc_func) {
+ tmp->dealloc_func(tmp->data_ptr);
+ }
+ free(tmp);
+ }
+
+ tmp = NULL;
+ } else {
+ tmp = tmp->next;
+ }
+ }
+
+ return eLINKED_LIST_SUCCESS;
+}
+
diff --git a/gps/utils/linked_list.h b/gps/utils/linked_list.h
new file mode 100644
index 0000000..0b33ecb
--- /dev/null
+++ b/gps/utils/linked_list.h
@@ -0,0 +1,219 @@
+/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __LINKED_LIST_H__
+#define __LINKED_LIST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+/** Linked List Return Codes */
+typedef enum
+{
+ eLINKED_LIST_SUCCESS = 0,
+ /**< Request was successful. */
+ eLINKED_LIST_FAILURE_GENERAL = -1,
+ /**< Failed because of a general failure. */
+ eLINKED_LIST_INVALID_PARAMETER = -2,
+ /**< Failed because the request contained invalid parameters. */
+ eLINKED_LIST_INVALID_HANDLE = -3,
+ /**< Failed because an invalid handle was specified. */
+ eLINKED_LIST_UNAVAILABLE_RESOURCE = -4,
+ /**< Failed because an there were not enough resources. */
+ eLINKED_LIST_INSUFFICIENT_BUFFER = -5,
+ /**< Failed because an the supplied buffer was too small. */
+ eLINKED_LIST_EMPTY = -6
+ /**< Failed because list is empty. */
+}linked_list_err_type;
+
+/*===========================================================================
+FUNCTION linked_list_init
+
+DESCRIPTION
+ Initializes internal structures for linked list.
+
+ list_data: State of list to be initialized.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_init(void** list_data);
+
+/*===========================================================================
+FUNCTION linked_list_destroy
+
+DESCRIPTION
+ Destroys internal structures for linked list.
+
+ p_list_data: State of list to be destroyed.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_destroy(void** list_data);
+
+/*===========================================================================
+FUNCTION linked_list_add
+
+DESCRIPTION
+ Adds an element to the head of the linked list. The passed in data pointer
+ is not modified or freed. Passed in data_obj is expected to live throughout
+ the use of the linked_list (i.e. data is not allocated internally)
+
+ p_list_data: List to add data to the head of.
+ data_obj: Pointer to data to add into list
+ dealloc: Function used to deallocate memory for this element. Pass NULL
+ if you do not want data deallocated during a flush operation
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*));
+
+/*===========================================================================
+FUNCTION linked_list_remove
+
+DESCRIPTION
+ Retrieves data from the list tail. data_obj is the tail element from the list
+ passed in by linked_list_add.
+
+ p_list_data: List to remove the tail from.
+ data_obj: Pointer to data removed from list
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_remove(void* list_data, void **data_obj);
+
+/*===========================================================================
+FUNCTION linked_list_empty
+
+DESCRIPTION
+ Tells whether the list currently contains any elements
+
+ p_list_data: List to check if empty.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0/FALSE : List contains elements
+ 1/TRUE : List is Empty
+ Otherwise look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+int linked_list_empty(void* list_data);
+
+/*===========================================================================
+FUNCTION linked_list_flush
+
+DESCRIPTION
+ Removes all elements from the list and deallocates them using the provided
+ dealloc function while adding elements.
+
+ p_list_data: List to remove all elements from.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_flush(void* list_data);
+
+/*===========================================================================
+FUNCTION linked_list_search
+
+DESCRIPTION
+ Searches for an element in the linked list.
+
+ p_list_data: List handle.
+ data_p: to be stored with the data found; NUll if no match.
+ if data_p passed in as NULL, then no write to it.
+ equal: Function ptr takes in a list element, and returns
+ indication if this the one looking for.
+ data_0: The data being compared against.
+ rm_if_found: Should data be removed if found?
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+linked_list_err_type linked_list_search(void* list_data, void **data_p,
+ bool (*equal)(void* data_0, void* data),
+ void* data_0, bool rm_if_found);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LINKED_LIST_H__ */
diff --git a/gps/utils/loc_cfg.cpp b/gps/utils/loc_cfg.cpp
new file mode 100644
index 0000000..2a89966
--- /dev/null
+++ b/gps/utils/loc_cfg.cpp
@@ -0,0 +1,1140 @@
+/* Copyright (c) 2011-2015, 2018-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_utils_cfg"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <grp.h>
+#include <errno.h>
+#include <loc_cfg.h>
+#include <loc_pla.h>
+#include <loc_target.h>
+#include <loc_misc_utils.h>
+#ifdef USE_GLIB
+#include <glib.h>
+#endif
+#include "log_util.h"
+
+/*=============================================================================
+ *
+ * GLOBAL DATA DECLARATION
+ *
+ *============================================================================*/
+
+/* Parameter data */
+static uint32_t DEBUG_LEVEL = 0xff;
+static uint32_t TIMESTAMP = 0;
+static uint32_t DATUM_TYPE = 0;
+static bool sVendorEnhanced = true;
+static uint32_t sLogBufferEnabled = 0;
+
+/* Parameter spec table */
+static const loc_param_s_type loc_param_table[] =
+{
+ {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'},
+ {"TIMESTAMP", &TIMESTAMP, NULL, 'n'},
+ {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'},
+ {"LOG_BUFFER_ENABLED", &sLogBufferEnabled, NULL, 'n'},
+};
+static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
+
+typedef struct loc_param_v_type
+{
+ char* param_name;
+ char* param_str_value;
+ int param_int_value;
+ double param_double_value;
+}loc_param_v_type;
+
+// Reference below arrays wherever needed to avoid duplicating
+// same conf path string over and again in location code.
+const char LOC_PATH_GPS_CONF[] = LOC_PATH_GPS_CONF_STR;
+const char LOC_PATH_IZAT_CONF[] = LOC_PATH_IZAT_CONF_STR;
+const char LOC_PATH_FLP_CONF[] = LOC_PATH_FLP_CONF_STR;
+const char LOC_PATH_LOWI_CONF[] = LOC_PATH_LOWI_CONF_STR;
+const char LOC_PATH_SAP_CONF[] = LOC_PATH_SAP_CONF_STR;
+const char LOC_PATH_APDR_CONF[] = LOC_PATH_APDR_CONF_STR;
+const char LOC_PATH_XTWIFI_CONF[] = LOC_PATH_XTWIFI_CONF_STR;
+const char LOC_PATH_QUIPC_CONF[] = LOC_PATH_QUIPC_CONF_STR;
+const char LOC_PATH_ANT_CORR[] = LOC_PATH_ANT_CORR_STR;
+const char LOC_PATH_SLIM_CONF[] = LOC_PATH_SLIM_CONF_STR;
+const char LOC_PATH_VPE_CONF[] = LOC_PATH_VPE_CONF_STR;
+
+bool isVendorEnhanced() {
+ return sVendorEnhanced;
+}
+void setVendorEnhanced(bool vendorEnhanced) {
+ sVendorEnhanced = vendorEnhanced;
+}
+
+/*===========================================================================
+FUNCTION loc_get_datum_type
+
+DESCRIPTION
+ get datum type
+
+PARAMETERS:
+ N/A
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ DATUM TYPE
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_get_datum_type()
+{
+ return DATUM_TYPE;
+}
+
+/*===========================================================================
+FUNCTION loc_set_config_entry
+
+DESCRIPTION
+ Potentially sets a given configuration table entry based on the passed in
+ configuration value. This is done by using a string comparison of the
+ parameter names and those found in the configuration file.
+
+PARAMETERS:
+ config_entry: configuration entry in the table to possibly set
+ config_value: value to store in the entry if the parameter names match
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_set_config_entry(const loc_param_s_type* config_entry,
+ loc_param_v_type* config_value,
+ uint16_t string_len = LOC_MAX_PARAM_STRING)
+{
+ int ret=-1;
+ if(NULL == config_entry || NULL == config_value)
+ {
+ LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__);
+ return ret;
+ }
+
+ if (strcmp(config_entry->param_name, config_value->param_name) == 0 &&
+ config_entry->param_ptr)
+ {
+ switch (config_entry->param_type)
+ {
+ case 's':
+ if (strcmp(config_value->param_str_value, "NULL") == 0)
+ {
+ *((char*)config_entry->param_ptr) = '\0';
+ }
+ else {
+ strlcpy((char*) config_entry->param_ptr,
+ config_value->param_str_value,
+ string_len);
+ }
+ /* Log INI values */
+ LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__,
+ config_entry->param_name, (char*)config_entry->param_ptr);
+
+ if(NULL != config_entry->param_set)
+ {
+ *(config_entry->param_set) = 1;
+ }
+ ret = 0;
+ break;
+ case 'n':
+ *((int *)config_entry->param_ptr) = config_value->param_int_value;
+ /* Log INI values */
+ LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__,
+ config_entry->param_name, config_value->param_int_value);
+
+ if(NULL != config_entry->param_set)
+ {
+ *(config_entry->param_set) = 1;
+ }
+ ret = 0;
+ break;
+ case 'f':
+ *((double *)config_entry->param_ptr) = config_value->param_double_value;
+ /* Log INI values */
+ LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__,
+ config_entry->param_name, config_value->param_double_value);
+
+ if(NULL != config_entry->param_set)
+ {
+ *(config_entry->param_set) = 1;
+ }
+ ret = 0;
+ break;
+ default:
+ LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s",
+ __FUNCTION__, config_entry->param_name);
+ }
+ }
+ return ret;
+}
+
+/*===========================================================================
+FUNCTION loc_fill_conf_item
+
+DESCRIPTION
+ Takes a line of configuration item and sets defined values based on
+ the passed in configuration table. This table maps strings to values to
+ set along with the type of each of these values.
+
+PARAMETERS:
+ input_buf : buffer contanis config item
+ config_table: table definition of strings to places to store information
+ table_length: length of the configuration table
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0: Number of records in the config_table filled with input_buf
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_fill_conf_item(char* input_buf,
+ const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len = LOC_MAX_PARAM_STRING)
+{
+ int ret = 0;
+
+ if (input_buf && config_table) {
+ char *lasts;
+ loc_param_v_type config_value;
+ memset(&config_value, 0, sizeof(config_value));
+
+ /* Separate variable and value */
+ config_value.param_name = strtok_r(input_buf, "=", &lasts);
+ /* skip lines that do not contain "=" */
+ if (config_value.param_name) {
+ config_value.param_str_value = strtok_r(NULL, "\0", &lasts);
+
+ /* skip lines that do not contain two operands */
+ if (config_value.param_str_value) {
+ /* Trim leading and trailing spaces */
+ loc_util_trim_space(config_value.param_name);
+ loc_util_trim_space(config_value.param_str_value);
+
+ /* Parse numerical value */
+ if ((strlen(config_value.param_str_value) >=3) &&
+ (config_value.param_str_value[0] == '0') &&
+ (tolower(config_value.param_str_value[1]) == 'x'))
+ {
+ /* hex */
+ config_value.param_int_value = (int) strtol(&config_value.param_str_value[2],
+ (char**) NULL, 16);
+ }
+ else {
+ config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */
+ config_value.param_int_value = atoi(config_value.param_str_value); /* dec */
+ }
+
+ for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
+ {
+ if(!loc_set_config_entry(&config_table[i], &config_value, string_len)) {
+ ret += 1;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*===========================================================================
+FUNCTION loc_read_conf_r_long (repetitive)
+
+DESCRIPTION
+ Reads the specified configuration file and sets defined values based on
+ the passed in configuration table. This table maps strings to values to
+ set along with the type of each of these values.
+ The difference between this and loc_read_conf is that this function returns
+ the file pointer position at the end of filling a config table. Also, it
+ reads a fixed number of parameters at a time which is equal to the length
+ of the configuration table. This functionality enables the caller to
+ repeatedly call the function to read data from the same file.
+
+PARAMETERS:
+ conf_fp : file pointer
+ config_table: table definition of strings to places to store information
+ table_length: length of the configuration table
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ 0: Table filled successfully
+ 1: No more parameters to read
+ -1: Error filling table
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len)
+{
+ int ret=0;
+ char input_buf[string_len]; /* declare a char array */
+ unsigned int num_params=table_length;
+
+ if(conf_fp == NULL) {
+ LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__);
+ ret = -1;
+ goto err;
+ }
+
+ /* Clear all validity bits */
+ for(uint32_t i = 0; NULL != config_table && i < table_length; i++)
+ {
+ if(NULL != config_table[i].param_set)
+ {
+ *(config_table[i].param_set) = 0;
+ }
+ }
+
+ LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
+ while(num_params)
+ {
+ if(!fgets(input_buf, string_len, conf_fp)) {
+ LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__);
+ break;
+ }
+
+ num_params -= loc_fill_conf_item(input_buf, config_table, table_length, string_len);
+ }
+
+err:
+ return ret;
+}
+
+/*===========================================================================
+FUNCTION loc_udpate_conf_long
+
+DESCRIPTION
+ Parses the passed in buffer for configuration items, and update the table
+ that is also passed in.
+
+Reads the specified configuration file and sets defined values based on
+ the passed in configuration table. This table maps strings to values to
+ set along with the type of each of these values.
+
+PARAMETERS:
+ conf_data: configuration items in bufferas a string
+ length: strlen(conf_data)
+ config_table: table definition of strings to places to store information
+ table_length: length of the configuration table
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ number of the records in the table that is updated at time of return.
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+int loc_update_conf_long(const char* conf_data, int32_t length,
+ const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len)
+{
+ int ret = -1;
+
+ if (conf_data && length && config_table && table_length) {
+ // make a copy, so we do not tokenize the original data
+ char* conf_copy = (char*)malloc(length+1);
+
+ if (conf_copy != NULL)
+ {
+ memcpy(conf_copy, conf_data, length);
+ // we hard NULL the end of string to be safe
+ conf_copy[length] = 0;
+
+ // start with one record off
+ uint32_t num_params = table_length - 1;
+ char* saveptr = NULL;
+ char* input_buf = strtok_r(conf_copy, "\n", &saveptr);
+ ret = 0;
+
+ LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params);
+ while(num_params && input_buf) {
+ ret++;
+ num_params -=
+ loc_fill_conf_item(input_buf, config_table, table_length, string_len);
+ input_buf = strtok_r(NULL, "\n", &saveptr);
+ }
+ free(conf_copy);
+ }
+ }
+
+ return ret;
+}
+
+/*===========================================================================
+FUNCTION loc_read_conf_long
+
+DESCRIPTION
+ Reads the specified configuration file and sets defined values based on
+ the passed in configuration table. This table maps strings to values to
+ set along with the type of each of these values.
+
+PARAMETERS:
+ conf_file_name: configuration file to read
+ config_table: table definition of strings to places to store information
+ table_length: length of the configuration table
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+void loc_read_conf_long(const char* conf_file_name, const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len)
+{
+ FILE *conf_fp = NULL;
+
+ log_buffer_init(false);
+ if((conf_fp = fopen(conf_file_name, "r")) != NULL)
+ {
+ LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
+ if(table_length && config_table) {
+ loc_read_conf_r_long(conf_fp, config_table, table_length, string_len);
+ rewind(conf_fp);
+ }
+ loc_read_conf_r_long(conf_fp, loc_param_table, loc_param_num, string_len);
+ fclose(conf_fp);
+ }
+ /* Initialize logging mechanism with parsed data */
+ loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
+ log_buffer_init(sLogBufferEnabled);
+ log_tag_level_map_init();
+}
+
+/*=============================================================================
+ *
+ * Define and Structures for Parsing Location Process Configuration File
+ *
+ *============================================================================*/
+#define MAX_NUM_STRINGS 20
+
+//We can have 8 masks for now
+#define CONFIG_MASK_TARGET_ALL 0X01
+#define CONFIG_MASK_TARGET_FOUND 0X02
+#define CONFIG_MASK_TARGET_CHECK 0X03
+#define CONFIG_MASK_BASEBAND_ALL 0X04
+#define CONFIG_MASK_BASEBAND_FOUND 0X08
+#define CONFIG_MASK_BASEBAND_CHECK 0x0c
+#define CONFIG_MASK_AUTOPLATFORM_ALL 0x10
+#define CONFIG_MASK_AUTOPLATFORM_FOUND 0x20
+#define CONFIG_MASK_AUTOPLATFORM_CHECK 0x30
+#define CONFIG_MASK_SOCID_ALL 0x40
+#define CONFIG_MASK_SOCID_FOUND 0x80
+#define CONFIG_MASK_SOCID_CHECK 0xc0
+
+#define LOC_FEATURE_MASK_GTP_WIFI_BASIC 0x01
+#define LOC_FEATURE_MASK_GTP_WIFI_PREMIUM 0X02
+#define LOC_FEATURE_MASK_GTP_CELL_BASIC 0X04
+#define LOC_FEATURE_MASK_GTP_CELL_PREMIUM 0X08
+#define LOC_FEATURE_MASK_SAP_BASIC 0x40
+#define LOC_FEATURE_MASK_SAP_PREMIUM 0X80
+#define LOC_FEATURE_MASK_GTP_WAA_BASIC 0X100
+#define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC 0X400
+#define LOC_FEATURE_MASK_ODCPI 0x1000
+#define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT 0x2000
+#define LOC_FEATURE_MASK_SUPL_WIFI 0x4000
+#define LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO 0x8000
+
+typedef struct {
+ char proc_name[LOC_MAX_PARAM_STRING];
+ char proc_argument[LOC_MAX_PARAM_STRING];
+ char proc_status[LOC_MAX_PARAM_STRING];
+ char group_list[LOC_MAX_PARAM_STRING];
+ unsigned int premium_feature;
+ unsigned int loc_feature_mask;
+ char platform_list[LOC_MAX_PARAM_STRING];
+ char baseband[LOC_MAX_PARAM_STRING];
+ char low_ram_targets[LOC_MAX_PARAM_STRING];
+ char soc_id_list[LOC_MAX_PARAM_STRING];
+ unsigned int sglte_target;
+ char feature_gtp_mode[LOC_MAX_PARAM_STRING];
+ char feature_gtp_waa[LOC_MAX_PARAM_STRING];
+ char feature_sap[LOC_MAX_PARAM_STRING];
+ char feature_odcpi[LOC_MAX_PARAM_STRING];
+ char feature_free_wifi_scan_inject[LOC_MAX_PARAM_STRING];
+ char feature_supl_wifi[LOC_MAX_PARAM_STRING];
+ char feature_wifi_supplicant_info[LOC_MAX_PARAM_STRING];
+ char auto_platform[LOC_MAX_PARAM_STRING];
+ unsigned int vendor_enhanced_process;
+} loc_launcher_conf;
+
+/* process configuration parameters */
+static loc_launcher_conf conf;
+
+/* gps.conf Parameter spec table */
+static const loc_param_s_type gps_conf_parameter_table[] = {
+ {"SGLTE_TARGET", &conf.sglte_target, NULL, 'n'},
+};
+
+/* location feature conf, e.g.: izat.conf feature mode table*/
+static const loc_param_s_type loc_feature_conf_table[] = {
+ {"GTP_MODE", &conf.feature_gtp_mode, NULL, 's'},
+ {"GTP_WAA", &conf.feature_gtp_waa, NULL, 's'},
+ {"SAP", &conf.feature_sap, NULL, 's'},
+ {"ODCPI", &conf.feature_odcpi, NULL, 's'},
+ {"FREE_WIFI_SCAN_INJECT", &conf.feature_free_wifi_scan_inject, NULL, 's'},
+ {"SUPL_WIFI", &conf.feature_supl_wifi, NULL, 's'},
+ {"WIFI_SUPPLICANT_INFO", &conf.feature_wifi_supplicant_info, NULL, 's'},
+};
+
+/* location process conf, e.g.: izat.conf Parameter spec table */
+static const loc_param_s_type loc_process_conf_parameter_table[] = {
+ {"PROCESS_NAME", &conf.proc_name, NULL, 's'},
+ {"PROCESS_ARGUMENT", &conf.proc_argument, NULL, 's'},
+ {"PROCESS_STATE", &conf.proc_status, NULL, 's'},
+ {"PROCESS_GROUPS", &conf.group_list, NULL, 's'},
+ {"PREMIUM_FEATURE", &conf.premium_feature, NULL, 'n'},
+ {"IZAT_FEATURE_MASK", &conf.loc_feature_mask, NULL, 'n'},
+ {"PLATFORMS", &conf.platform_list, NULL, 's'},
+ {"SOC_IDS", &conf.soc_id_list, NULL, 's'},
+ {"BASEBAND", &conf.baseband, NULL, 's'},
+ {"LOW_RAM_TARGETS", &conf.low_ram_targets, NULL, 's'},
+ {"HARDWARE_TYPE", &conf.auto_platform, NULL, 's'},
+ {"VENDOR_ENHANCED_PROCESS", &conf.vendor_enhanced_process, NULL, 'n'},
+};
+
+/*===========================================================================
+FUNCTION loc_read_process_conf
+
+DESCRIPTION
+ Parse the specified conf file and return info for the processes defined.
+ The format of the file should conform with izat.conf.
+
+PARAMETERS:
+ conf_file_name: configuration file to read
+ process_count_ptr: pointer to store number of processes defined in the conf file.
+ process_info_table_ptr: pointer to store the process info table.
+
+DEPENDENCIES
+ The file must be in izat.conf format.
+
+RETURN VALUE
+ 0: success
+ none-zero: failure
+
+SIDE EFFECTS
+ N/A
+
+NOTES:
+ On success, memory pointed by (*process_info_table_ptr) must be freed.
+===========================================================================*/
+int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
+ loc_process_info_s_type** process_info_table_ptr) {
+ loc_process_info_s_type *child_proc = nullptr;
+ volatile int i=0;
+ unsigned int j=0;
+ gid_t gid_list[LOC_PROCESS_MAX_NUM_GROUPS];
+ char *split_strings[MAX_NUM_STRINGS];
+ int name_length=0, group_list_length=0, platform_length=0, baseband_length=0, ngroups=0, ret=0;
+ int auto_platform_length = 0, soc_id_list_length=0;
+ int group_index=0, nstrings=0, status_length=0;
+ FILE* conf_fp = nullptr;
+ char platform_name[PROPERTY_VALUE_MAX], baseband_name[PROPERTY_VALUE_MAX];
+ int low_ram_target=0;
+ char autoplatform_name[PROPERTY_VALUE_MAX], socid_value[PROPERTY_VALUE_MAX];
+ unsigned int loc_service_mask=0;
+ unsigned char config_mask = 0;
+ unsigned char proc_list_length=0;
+ int gtp_cell_ap_enabled = 0;
+ char arg_gtp_waa[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
+ char arg_gtp_modem_cell[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
+ char arg_gtp_wifi[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
+ char arg_sap[LOC_PROCESS_MAX_ARG_STR_LENGTH] = "--";
+ char arg_disabled[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_DISABLED;
+ char arg_basic[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_BASIC;
+ char arg_premium[LOC_PROCESS_MAX_ARG_STR_LENGTH] = LOC_FEATURE_MODE_PREMIUM;
+
+ if (process_count_ptr == NULL || process_info_table_ptr == NULL) {
+ return -1;
+ }
+
+ //Read gps.conf and fill parameter table
+ UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_parameter_table);
+
+ //Form argument strings
+ strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
+ strlcat(arg_gtp_modem_cell, LOC_FEATURE_GTP_MODEM_CELL, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
+ strlcat(arg_gtp_wifi, LOC_FEATURE_GTP_WIFI, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
+ strlcat(arg_sap, LOC_FEATURE_SAP, LOC_PROCESS_MAX_ARG_STR_LENGTH-3);
+
+ //Get platform name from ro.board.platform property
+ loc_get_platform_name(platform_name, sizeof(platform_name));
+ //Get baseband name from ro.baseband property
+ loc_get_target_baseband(baseband_name, sizeof(baseband_name));
+ //Identify if this is an automotive platform
+ loc_get_auto_platform_name(autoplatform_name,sizeof(autoplatform_name));
+ //Identify if this is a low ram target from ro.config.low_ram property
+ low_ram_target = loc_identify_low_ram_target();
+ // Get the soc-id for this device.
+ loc_get_device_soc_id(socid_value, sizeof(socid_value));
+
+ UTIL_READ_CONF(conf_file_name, loc_feature_conf_table);
+
+ //Set service mask for GTP_MODE
+ if (strcmp(conf.feature_gtp_mode, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: GTP MODE DISABLED", __func__, __LINE__);
+ }
+ else if (strcmp(conf.feature_gtp_mode, "LEGACY_WWAN") == 0) {
+ LOC_LOGD("%s:%d]: Setting GTP MODE to mode: LEGACY_WWAN", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC;
+ }
+ else if (strcmp(conf.feature_gtp_mode, "SDK") == 0) {
+ LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
+ }
+ else if (strcmp(conf.feature_gtp_mode, "SDK_WIFI") == 0) {
+ LOC_LOGD("%s:%d]: Setting GTP MODE to mode: SDK", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC;
+ }
+ //conf file has a garbage value
+ else {
+ LOC_LOGE("%s:%d]: Unrecognized value for GTP MODE Mode."\
+ " Setting GTP WIFI to default mode: DISABLED", __func__, __LINE__);
+ }
+ //Set service mask for GTP_WAA
+ if (strcmp(conf.feature_gtp_waa, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting GTP WAA to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC;
+ }
+ else if (strcmp(conf.feature_gtp_waa, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: GTP WAA DISABLED", __func__, __LINE__);
+ }
+ //conf file has a garbage value
+ else {
+ LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\
+ " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__);
+ }
+
+ //Set service mask for SAP
+ if(strcmp(conf.feature_sap, "PREMIUM") == 0 ||
+ strcmp(conf.feature_sap, "PREMIUM_ENV_AIDING") == 0) {
+ LOC_LOGD("%s:%d]: Setting SAP to mode: PREMIUM", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SAP_PREMIUM;
+ }
+ else if (strcmp(conf.feature_sap, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting SAP to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
+ }
+ else if (strcmp(conf.feature_sap, "MODEM_DEFAULT") == 0) {
+ LOC_LOGD("%s:%d]: Setting SAP to mode: MODEM_DEFAULT", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
+ }
+ else if (strcmp(conf.feature_sap, "DISABLED") == 0) {
+#ifdef USE_GLIB
+ /* Enable slim_daemon even when SAP is set to DISABLED*/
+ loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
+#else
+ LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__);
+#endif
+ }
+ else {
+ LOC_LOGE("%s:%d]: Unrecognized value for SAP Mode."\
+ " Setting SAP to default mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SAP_BASIC;
+ }
+
+ // Set service mask for ODCPI
+ if (strcmp(conf.feature_odcpi, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting ODCPI to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
+ }
+ else if (strcmp(conf.feature_odcpi, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: Setting ODCPI to mode: DISABLED", __func__, __LINE__);
+ }
+ else if (strcmp(conf.feature_odcpi, "PREMIUM") == 0) {
+ LOC_LOGD("%s:%d]: Unrecognized value for ODCPI mode."\
+ "Setting ODCPI to default mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_ODCPI;
+ }
+
+ // Set service mask for FREE_WIFI_SCAN_INJECT
+ if (strcmp(conf.feature_free_wifi_scan_inject, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
+ }
+ else if (strcmp(conf.feature_free_wifi_scan_inject, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: Setting FREE_WIFI_SCAN_INJECT to mode: DISABLED", __func__, __LINE__);
+ }
+ else if (strcmp(conf.feature_free_wifi_scan_inject, "PREMIUM") == 0) {
+ LOC_LOGD("%s:%d]: Unrecognized value for FREE_WIFI_SCAN_INJECT mode."\
+ "Setting FREE_WIFI_SCAN_INJECT to default mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT;
+ }
+
+ // Set service mask for SUPL_WIFI
+ if (strcmp(conf.feature_supl_wifi, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
+ }
+ else if (strcmp(conf.feature_supl_wifi, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: Setting SUPL_WIFI to mode: DISABLED", __func__, __LINE__);
+ }
+ else if (strcmp(conf.feature_supl_wifi, "PREMIUM") == 0) {
+ LOC_LOGD("%s:%d]: Unrecognized value for SUPL_WIFI mode."\
+ "Setting SUPL_WIFI to default mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_SUPL_WIFI;
+ }
+
+ // Set service mask for WIFI_SUPPLICANT_INFO
+ if (strcmp(conf.feature_wifi_supplicant_info, "BASIC") == 0) {
+ LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
+ }
+ else if (strcmp(conf.feature_wifi_supplicant_info, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: Setting WIFI_SUPPLICANT_INFO to mode: DISABLED", __func__, __LINE__);
+ }
+ else if (strcmp(conf.feature_wifi_supplicant_info, "PREMIUM") == 0) {
+ LOC_LOGD("%s:%d]: Unrecognized value for WIFI_SUPPLICANT_INFO mode."\
+ "Setting LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO to default mode: BASIC", __func__, __LINE__);
+ loc_service_mask |= LOC_FEATURE_MASK_WIFI_SUPPLICANT_INFO;
+ }
+
+ LOC_LOGD("%s:%d]: loc_service_mask: %x\n", __func__, __LINE__, loc_service_mask);
+
+ if((conf_fp = fopen(conf_file_name, "r")) == NULL) {
+ LOC_LOGE("%s:%d]: Error opening %s %s\n", __func__,
+ __LINE__, conf_file_name, strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ //Parse through the file to find out how many processes are to be launched
+ proc_list_length = 0;
+ do {
+ conf.proc_name[0] = 0;
+ //Here note that the 3rd parameter is passed as 1.
+ //This is so that only the first parameter in the table which is "PROCESS_NAME"
+ //is read. We do not want to read the entire block of parameters at this time
+ //since we are only counting the number of processes to launch.
+ //Therefore, only counting the occurrences of PROCESS_NAME parameter
+ //should suffice
+ if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table, 1)) {
+ LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
+ ret = -1;
+ goto err;
+ }
+ name_length=(int)strlen(conf.proc_name);
+ if(name_length) {
+ proc_list_length++;
+ LOC_LOGD("Process name:%s", conf.proc_name);
+ }
+ } while(name_length);
+ LOC_LOGD("Process cnt = %d", proc_list_length);
+
+ child_proc = (loc_process_info_s_type *)calloc(proc_list_length, sizeof(loc_process_info_s_type));
+ if(child_proc == NULL) {
+ LOC_LOGE("%s:%d]: ERROR: Malloc returned NULL\n", __func__, __LINE__);
+ ret = -1;
+ goto err;
+ }
+
+ //Move file descriptor to the beginning of the file
+ //so that the parameters can be read
+ rewind(conf_fp);
+
+ for(j=0; j<proc_list_length; j++) {
+ //Set defaults for all the child process structs
+ child_proc[j].proc_status = DISABLED;
+ memset(child_proc[j].group_list, 0, sizeof(child_proc[j].group_list));
+ config_mask=0;
+ if(loc_read_conf_r(conf_fp, loc_process_conf_parameter_table,
+ sizeof(loc_process_conf_parameter_table)/sizeof(loc_process_conf_parameter_table[0]))) {
+ LOC_LOGE("%s:%d]: Unable to read conf file. Failing\n", __func__, __LINE__);
+ ret = -1;
+ goto err;
+ }
+
+ name_length=(int)strlen(conf.proc_name);
+ group_list_length=(int)strlen(conf.group_list);
+ platform_length = (int)strlen(conf.platform_list);
+ baseband_length = (int)strlen(conf.baseband);
+ status_length = (int)strlen(conf.proc_status);
+ auto_platform_length = (int)strlen(conf.auto_platform);
+ soc_id_list_length = (int)strlen(conf.soc_id_list);
+
+ if(!name_length || !group_list_length || !platform_length ||
+ !baseband_length || !status_length || !auto_platform_length || !soc_id_list_length) {
+ LOC_LOGE("%s:%d]: Error: i: %d; One of the parameters not specified in conf file",
+ __func__, __LINE__, i);
+ continue;
+ }
+
+ if (!isVendorEnhanced() && (conf.vendor_enhanced_process != 0)) {
+ LOC_LOGD("%s:%d]: Process %s is disabled via vendor enhanced process check",
+ __func__, __LINE__, conf.proc_name);
+ child_proc[j].proc_status = DISABLED_VIA_VENDOR_ENHANCED_CHECK;
+ continue;
+ }
+
+ if (strcmp(conf.proc_status, "DISABLED") == 0) {
+ LOC_LOGD("%s:%d]: Process %s is disabled in conf file",
+ __func__, __LINE__, conf.proc_name);
+ child_proc[j].proc_status = DISABLED_FROM_CONF;
+ continue;
+ }
+ else if (strcmp(conf.proc_status, "ENABLED") == 0) {
+ LOC_LOGD("%s:%d]: Process %s is enabled in conf file",
+ __func__, __LINE__, conf.proc_name);
+ }
+
+ //Since strlcpy copies length-1 characters, we add 1 to name_length
+ if((name_length+1) > LOC_MAX_PARAM_STRING) {
+ LOC_LOGE("%s:%d]: i: %d; Length of name parameter too long. Max length: %d",
+ __func__, __LINE__, i, LOC_MAX_PARAM_STRING);
+ continue;
+ }
+ strlcpy(child_proc[j].name[0], conf.proc_name, sizeof (child_proc[j].name[0]));
+
+ child_proc[j].num_groups = 0;
+ ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' ');
+ for(i=0; i<ngroups; i++) {
+ struct group* grp = getgrnam(split_strings[i]);
+ if (grp) {
+ child_proc[j].group_list[child_proc[j].num_groups] = grp->gr_gid;
+ child_proc[j].num_groups++;
+ LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid);
+ }
+ }
+
+ nstrings = loc_util_split_string(conf.platform_list, split_strings, MAX_NUM_STRINGS, ' ');
+ if (strcmp("all", split_strings[0]) == 0) {
+ if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
+ LOC_LOGD("%s:%d]: Enabled for all targets\n", __func__, __LINE__);
+ config_mask |= CONFIG_MASK_TARGET_ALL;
+ }
+ else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
+ config_mask |= CONFIG_MASK_TARGET_FOUND;
+ for (i=2; i<nstrings; i++) {
+ if (strcmp(platform_name, split_strings[i]) == 0) {
+ LOC_LOGD("%s:%d]: Disabled platform %s\n", __func__, __LINE__, platform_name);
+ config_mask &= ~CONFIG_MASK_TARGET_FOUND;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ for(i=0; i<nstrings; i++) {
+ if (strcmp(platform_name, split_strings[i]) == 0) {
+ LOC_LOGD("%s:%d]: Matched platform: %s\n",
+ __func__, __LINE__, split_strings[i]);
+ config_mask |= CONFIG_MASK_TARGET_FOUND;
+ break;
+ }
+ }
+ }
+
+ // SOC Id's check
+ nstrings = loc_util_split_string(conf.soc_id_list, split_strings, MAX_NUM_STRINGS, ' ');
+ if (strcmp("all", split_strings[0]) == 0) {
+ if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
+ LOC_LOGd("Enabled for all SOC ids\n");
+ config_mask |= CONFIG_MASK_SOCID_ALL;
+ }
+ else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
+ config_mask |= CONFIG_MASK_SOCID_FOUND;
+ for (i = 2; i < nstrings; i++) {
+ if (strcmp(socid_value, split_strings[i]) == 0) {
+ LOC_LOGd("Disabled for SOC id %s\n", socid_value);
+ config_mask &= ~CONFIG_MASK_SOCID_FOUND;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ for (i = 0; i < nstrings; i++) {
+ if (strcmp(socid_value, split_strings[i]) == 0) {
+ LOC_LOGd("Matched SOC id : %s\n", split_strings[i]);
+ config_mask |= CONFIG_MASK_SOCID_FOUND;
+ break;
+ }
+ }
+ }
+
+ nstrings = loc_util_split_string(conf.baseband, split_strings, MAX_NUM_STRINGS, ' ');
+ if (strcmp("all", split_strings[0]) == 0) {
+ if (nstrings == 1 || (nstrings == 2 && (strcmp("exclude", split_strings[1]) == 0))) {
+ LOC_LOGD("%s:%d]: Enabled for all basebands\n", __func__, __LINE__);
+ config_mask |= CONFIG_MASK_BASEBAND_ALL;
+ }
+ else if (nstrings > 2 && (strcmp("exclude", split_strings[1]) == 0)) {
+ config_mask |= CONFIG_MASK_BASEBAND_FOUND;
+ for (i=2; i<nstrings; i++) {
+ if (strcmp(baseband_name, split_strings[i]) == 0) {
+ LOC_LOGD("%s:%d]: Disabled band %s\n", __func__, __LINE__, baseband_name);
+ config_mask &= ~CONFIG_MASK_BASEBAND_FOUND;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ for(i=0; i<nstrings; i++) {
+ if (strcmp(baseband_name, split_strings[i]) == 0) {
+ LOC_LOGD("%s:%d]: Matched baseband: %s\n",
+ __func__, __LINE__, split_strings[i]);
+ config_mask |= CONFIG_MASK_BASEBAND_FOUND;
+ break;
+ }
+ //Since ro.baseband is not a reliable source for detecting sglte
+ //the alternative is to read the SGLTE_TARGET parameter from gps.conf
+ //this parameter is read into conf_sglte_target
+ else if((strcmp("sglte", split_strings[i]) == 0 ) && conf.sglte_target) {
+ LOC_LOGD("%s:%d]: Matched baseband SGLTE\n", __func__, __LINE__);
+ config_mask |= CONFIG_MASK_BASEBAND_FOUND;
+ break;
+ }
+ }
+ }
+
+ nstrings = loc_util_split_string(conf.auto_platform, split_strings, MAX_NUM_STRINGS, ' ');
+ if (strcmp("all", split_strings[0]) == 0) {
+ LOC_LOGD("%s:%d]: Enabled for all auto platforms\n", __func__, __LINE__);
+ config_mask |= CONFIG_MASK_AUTOPLATFORM_ALL;
+ }
+ else {
+ for(i=0; i<nstrings; i++) {
+ if (strcmp(autoplatform_name, split_strings[i]) == 0) {
+ LOC_LOGD("%s:%d]: Matched auto platform: %s\n",
+ __func__, __LINE__, split_strings[i]);
+ config_mask |= CONFIG_MASK_AUTOPLATFORM_FOUND;
+ break;
+ }
+ }
+ }
+
+ nstrings = loc_util_split_string(conf.low_ram_targets, split_strings, MAX_NUM_STRINGS, ' ');
+ if (!strcmp("DISABLED", split_strings[0]) && low_ram_target) {
+ LOC_LOGd("Disabled for low ram targets\n");
+ child_proc[j].proc_status = DISABLED;
+ continue;
+ }
+
+ if((config_mask & CONFIG_MASK_TARGET_CHECK) &&
+ (config_mask & CONFIG_MASK_BASEBAND_CHECK) &&
+ (config_mask & CONFIG_MASK_AUTOPLATFORM_CHECK) &&
+ (config_mask & CONFIG_MASK_SOCID_CHECK) &&
+ (child_proc[j].proc_status != DISABLED_FROM_CONF) &&
+ (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) {
+
+ //Set args
+ //The first argument passed through argv is usually the name of the
+ //binary when started from commandline.
+ //getopt() seems to ignore this first argument and hence we assign it
+ //to the process name for consistency with command line args
+ i = 0;
+ char* temp_arg = ('/' == child_proc[j].name[0][0]) ?
+ (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0];
+ strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[0]));
+
+ if(conf.premium_feature) {
+ if(conf.loc_feature_mask & loc_service_mask) {
+ LOC_LOGD("%s:%d]: Enabled. %s has service mask: %x\n",
+ __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
+ child_proc[j].proc_status = ENABLED;
+
+ if(conf.loc_feature_mask &
+ (LOC_FEATURE_MASK_GTP_WIFI_BASIC | LOC_FEATURE_MASK_GTP_WIFI_PREMIUM)) {
+ if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_BASIC) {
+ strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_basic,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else if(loc_service_mask & LOC_FEATURE_MASK_GTP_WIFI_PREMIUM) {
+ strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_premium,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else
+ {
+ strlcpy(child_proc[j].args[i++], arg_gtp_wifi,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_disabled,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ }
+ if(conf.loc_feature_mask &
+ (LOC_FEATURE_MASK_GTP_CELL_BASIC | LOC_FEATURE_MASK_GTP_CELL_PREMIUM )) {
+ if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) {
+ strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_basic,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else {
+ strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_disabled,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ }
+ if(conf.loc_feature_mask &
+ (LOC_FEATURE_MASK_SAP_BASIC | LOC_FEATURE_MASK_SAP_PREMIUM)) {
+ if(loc_service_mask & LOC_FEATURE_MASK_SAP_BASIC) {
+ strlcpy(child_proc[j].args[i++], arg_sap,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_basic,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else if(loc_service_mask & LOC_FEATURE_MASK_SAP_PREMIUM) {
+ strlcpy(child_proc[j].args[i++], arg_sap,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_premium,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else
+ {
+ strlcpy(child_proc[j].args[i++], arg_sap,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_disabled,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ }
+
+ if(conf.loc_feature_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
+ if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_BASIC) {
+ strlcpy(child_proc[j].args[i++], arg_gtp_waa,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_basic,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ else
+ {
+ strlcpy(child_proc[j].args[i++], arg_gtp_waa,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ strlcpy(child_proc[j].args[i++], arg_disabled,
+ LOC_PROCESS_MAX_ARG_STR_LENGTH);
+ }
+ }
+ IF_LOC_LOGD {
+ LOC_LOGD("%s:%d]: %s args\n", __func__, __LINE__, child_proc[j].name[0]);
+ for(unsigned int k=0; k<LOC_PROCESS_MAX_NUM_ARGS; k++) {
+ if(child_proc[j].args[k][0] != '\0') {
+ LOC_LOGD("%s:%d]: k: %d, %s\n", __func__, __LINE__, k,
+ child_proc[j].args[k]);
+ }
+ }
+ LOC_LOGD("%s:%d]: \n", __func__, __LINE__);
+ }
+ }
+ else {
+ LOC_LOGD("%s:%d]: Disabled. %s has service mask: %x \n",
+ __func__, __LINE__, child_proc[j].name[0], conf.loc_feature_mask);
+ }
+ }
+ else {
+ LOC_LOGD("%s:%d]: %s not a premium feature. Enabled\n",
+ __func__, __LINE__, child_proc[j].name[0]);
+ child_proc[j].proc_status = ENABLED;
+ }
+
+ /*Fill up the remaining arguments from configuration file*/
+ LOC_LOGD("%s] Parsing Process_Arguments from Configuration: %s \n",
+ __func__, conf.proc_argument);
+ if(0 != conf.proc_argument[0])
+ {
+ /**************************************
+ ** conf_proc_argument is shared by all the programs getting launched,
+ ** hence copy to process specific argument string and parse the same.
+ ***************************************/
+ strlcpy(child_proc[j].argumentString, conf.proc_argument,
+ sizeof(child_proc[j].argumentString));
+ char *temp_args[LOC_PROCESS_MAX_NUM_ARGS];
+ memset (temp_args, 0, sizeof (temp_args));
+ loc_util_split_string(child_proc[j].argumentString, &temp_args[i],
+ (LOC_PROCESS_MAX_NUM_ARGS - i), ' ');
+ // copy argument from the pointer to the memory
+ for (unsigned int index = i; index < LOC_PROCESS_MAX_NUM_ARGS; index++) {
+ if (temp_args[index] == NULL) {
+ break;
+ }
+ strlcpy (child_proc[j].args[index], temp_args[index],
+ sizeof (child_proc[j].args[index]));
+ }
+ }
+ }
+ else {
+ LOC_LOGD("%s:%d]: Process %s is disabled\n",
+ __func__, __LINE__, child_proc[j].name[0]);
+ }
+ }
+
+err:
+ if (conf_fp) {
+ fclose(conf_fp);
+ }
+ if (ret != 0) {
+ LOC_LOGE("%s:%d]: ret: %d", __func__, __LINE__, ret);
+ if (child_proc) {
+ free (child_proc);
+ child_proc = nullptr;
+ }
+ *process_count_ptr = 0;
+ *process_info_table_ptr = nullptr;
+
+ }
+ else {
+ *process_count_ptr = proc_list_length;
+ *process_info_table_ptr = child_proc;
+ }
+
+ return ret;
+}
diff --git a/gps/utils/loc_cfg.h b/gps/utils/loc_cfg.h
new file mode 100644
index 0000000..e87d632
--- /dev/null
+++ b/gps/utils/loc_cfg.h
@@ -0,0 +1,167 @@
+/* Copyright (c) 2011-2015, 2018, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_CFG_H
+#define LOC_CFG_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+
+#define LOC_MAX_PARAM_NAME 80
+#define LOC_MAX_PARAM_STRING 172
+#define LOC_MAX_PARAM_LINE (LOC_MAX_PARAM_NAME + LOC_MAX_PARAM_STRING)
+
+#define LOC_FEATURE_MODE_DISABLED "DISABLED"
+#define LOC_FEATURE_MODE_BASIC "BASIC"
+#define LOC_FEATURE_MODE_PREMIUM "PREMIUM"
+
+#define LOC_FEATURE_GTP_AP_CELL "gtp-ap-cell"
+#define LOC_FEATURE_GTP_MODEM_CELL "gtp-modem-cell"
+#define LOC_FEATURE_GTP_CELL_ENH "gtp-cell-enh"
+#define LOC_FEATURE_GTP_WIFI "gtp-wifi"
+#define LOC_FEATURE_GTP_WAA "gtp-waa"
+#define LOC_FEATURE_SAP "sap"
+
+#define LOC_PROCESS_MAX_NUM_GROUPS 20
+#define LOC_PROCESS_MAX_NUM_ARGS 25
+#define LOC_PROCESS_MAX_ARG_STR_LENGTH 32
+
+#define UTIL_UPDATE_CONF(conf_data, len, config_table) \
+ loc_update_conf((conf_data), (len), (&config_table[0]), \
+ sizeof(config_table) / sizeof(config_table[0]))
+
+#define UTIL_READ_CONF_DEFAULT(filename) \
+ loc_read_conf((filename), NULL, 0);
+
+#define UTIL_READ_CONF(filename, config_table) \
+ loc_read_conf((filename), (&config_table[0]), sizeof(config_table) / sizeof(config_table[0]))
+
+#define UTIL_READ_CONF_LONG(filename, config_table, rec_len) \
+ loc_read_conf_long((filename), (&config_table[0]), \
+ sizeof(config_table) / sizeof(config_table[0]), (rec_len))
+
+/*=============================================================================
+ *
+ * MODULE TYPE DECLARATION
+ *
+ *============================================================================*/
+typedef struct
+{
+ const char *param_name;
+ void *param_ptr; /* for string type, buf size need to be LOC_MAX_PARAM_STRING */
+ uint8_t *param_set; /* indicate value set by config file */
+ char param_type; /* 'n' for number,
+ 's' for string, NOTE: buf size need to be LOC_MAX_PARAM_STRING
+ 'f' for double */
+} loc_param_s_type;
+
+typedef enum {
+ ENABLED,
+ RUNNING,
+ DISABLED,
+ DISABLED_FROM_CONF,
+ DISABLED_VIA_VENDOR_ENHANCED_CHECK
+} loc_process_e_status;
+
+typedef struct {
+ loc_process_e_status proc_status;
+ pid_t proc_id;
+ char name[2][LOC_MAX_PARAM_STRING];
+ gid_t group_list[LOC_PROCESS_MAX_NUM_GROUPS];
+ unsigned char num_groups;
+ char args[LOC_PROCESS_MAX_NUM_ARGS][LOC_PROCESS_MAX_ARG_STR_LENGTH];
+ char argumentString[LOC_MAX_PARAM_STRING];
+} loc_process_info_s_type;
+
+/*=============================================================================
+ *
+ * MODULE EXTERNAL DATA
+ *
+ *============================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=============================================================================
+ *
+ * MODULE EXPORTED FUNCTIONS
+ *
+ *============================================================================*/
+bool isVendorEnhanced();
+void setVendorEnhanced(bool vendorEnhanced);
+void loc_read_conf_long(const char* conf_file_name,
+ const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len);
+int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
+ uint32_t table_length, uint16_t string_len);
+int loc_update_conf_long(const char* conf_data, int32_t length,
+ const loc_param_s_type* config_table, uint32_t table_length,
+ uint16_t string_len);
+
+inline void loc_read_conf(const char* conf_file_name,
+ const loc_param_s_type* config_table, uint32_t table_length) {
+ loc_read_conf_long(conf_file_name, config_table, table_length, LOC_MAX_PARAM_STRING);
+}
+
+inline int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table,
+ uint32_t table_length) {
+ return (loc_read_conf_r_long(conf_fp, config_table, table_length, LOC_MAX_PARAM_STRING));
+}
+
+inline int loc_update_conf(const char* conf_data, int32_t length,
+ const loc_param_s_type* config_table, uint32_t table_length) {
+ return (loc_update_conf_long(
+ conf_data, length, config_table, table_length, LOC_MAX_PARAM_STRING));
+}
+
+// Below are the location conf file paths
+extern const char LOC_PATH_GPS_CONF[];
+extern const char LOC_PATH_IZAT_CONF[];
+extern const char LOC_PATH_FLP_CONF[];
+extern const char LOC_PATH_LOWI_CONF[];
+extern const char LOC_PATH_SAP_CONF[];
+extern const char LOC_PATH_APDR_CONF[];
+extern const char LOC_PATH_XTWIFI_CONF[];
+extern const char LOC_PATH_QUIPC_CONF[];
+extern const char LOC_PATH_ANT_CORR[];
+extern const char LOC_PATH_SLIM_CONF[];
+extern const char LOC_PATH_VPE_CONF[];
+
+int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
+ loc_process_info_s_type** process_info_table_ptr);
+int loc_get_datum_type();
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOC_CFG_H */
diff --git a/gps/utils/loc_gps.h b/gps/utils/loc_gps.h
new file mode 100644
index 0000000..90541c4
--- /dev/null
+++ b/gps/utils/loc_gps.h
@@ -0,0 +1,2235 @@
+/*
+ * Copyright (C) 2010 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 LOC_GPS_H
+#define LOC_GPS_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+#define LOC_FLP_STATUS_LOCATION_AVAILABLE 0
+#define LOC_FLP_STATUS_LOCATION_UNAVAILABLE 1
+#define LOC_CAPABILITY_GNSS (1U<<0)
+#define LOC_CAPABILITY_WIFI (1U<<1)
+#define LOC_CAPABILITY_CELL (1U<<3)
+
+/** Milliseconds since January 1, 1970 */
+typedef int64_t LocGpsUtcTime;
+
+/** Maximum number of SVs for loc_gps_sv_status_callback(). */
+#define LOC_GPS_MAX_SVS 32
+/** Maximum number of SVs for loc_gps_sv_status_callback(). */
+#define LOC_GNSS_MAX_SVS 64
+
+/** Maximum number of Measurements in loc_gps_measurement_callback(). */
+#define LOC_GPS_MAX_MEASUREMENT 32
+
+/** Maximum number of Measurements in loc_gnss_measurement_callback(). */
+#define LOC_GNSS_MAX_MEASUREMENT 64
+
+/** Requested operational mode for GPS operation. */
+typedef uint32_t LocGpsPositionMode;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Mode for running GPS standalone (no assistance). */
+#define LOC_GPS_POSITION_MODE_STANDALONE 0
+/** AGPS MS-Based mode. */
+#define LOC_GPS_POSITION_MODE_MS_BASED 1
+/**
+ * AGPS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use LOC_GPS_POSITION_MODE_MS_BASED instead.
+ */
+#define LOC_GPS_POSITION_MODE_MS_ASSISTED 2
+
+/** Requested recurrence mode for GPS operation. */
+typedef uint32_t LocGpsPositionRecurrence;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** Receive GPS fixes on a recurring basis at a specified period. */
+#define LOC_GPS_POSITION_RECURRENCE_PERIODIC 0
+/** Request a single shot GPS fix. */
+#define LOC_GPS_POSITION_RECURRENCE_SINGLE 1
+
+/** GPS status event values. */
+typedef uint16_t LocGpsStatusValue;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** GPS status unknown. */
+#define LOC_GPS_STATUS_NONE 0
+/** GPS has begun navigating. */
+#define LOC_GPS_STATUS_SESSION_BEGIN 1
+/** GPS has stopped navigating. */
+#define LOC_GPS_STATUS_SESSION_END 2
+/** GPS has powered on but is not navigating. */
+#define LOC_GPS_STATUS_ENGINE_ON 3
+/** GPS is powered off. */
+#define LOC_GPS_STATUS_ENGINE_OFF 4
+
+/** Flags to indicate which values are valid in a LocGpsLocation. */
+typedef uint16_t LocGpsLocationFlags;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+/** LocGpsLocation has valid latitude and longitude. */
+#define LOC_GPS_LOCATION_HAS_LAT_LONG 0x0001
+/** LocGpsLocation has valid altitude. */
+#define LOC_GPS_LOCATION_HAS_ALTITUDE 0x0002
+/** LocGpsLocation has valid speed. */
+#define LOC_GPS_LOCATION_HAS_SPEED 0x0004
+/** LocGpsLocation has valid bearing. */
+#define LOC_GPS_LOCATION_HAS_BEARING 0x0008
+/** LocGpsLocation has valid accuracy. */
+#define LOC_GPS_LOCATION_HAS_ACCURACY 0x0010
+/** LocGpsLocation has valid vertical uncertainity */
+#define LOC_GPS_LOCATION_HAS_VERT_UNCERTAINITY 0x0040
+/** LocGpsLocation has valid spoof mask */
+#define LOC_GPS_LOCATION_HAS_SPOOF_MASK 0x0080
+/** LocGpsLocation has valid speed accuracy */
+#define LOC_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0100
+/** LocGpsLocation has valid bearing accuracy */
+#define LOC_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0200
+/** LocGpsLocation has valid Real Time and Real Time Uncertainty */
+#define LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME 0x0400
+
+/** Spoof mask in LocGpsLocation */
+typedef uint32_t LocGpsSpoofMask;
+#define LOC_GPS_LOCATION_NONE_SPOOFED 0x0000
+#define LOC_GPS_LOCATION_POSITION_SPOOFED 0x0001
+#define LOC_GPS_LOCATION_TIME_SPOOFED 0x0002
+#define LOC_GPS_LOCATION_NAVIGATION_DATA_SPOOFED 0x0004
+
+/** Flags for the loc_gps_set_capabilities callback. */
+
+/**
+ * GPS HAL schedules fixes for LOC_GPS_POSITION_RECURRENCE_PERIODIC mode. If this is
+ * not set, then the framework will use 1000ms for min_interval and will start
+ * and call start() and stop() to schedule the GPS.
+ */
+#define LOC_GPS_CAPABILITY_SCHEDULING (1 << 0)
+/** GPS supports MS-Based AGPS mode */
+#define LOC_GPS_CAPABILITY_MSB (1 << 1)
+/** GPS supports MS-Assisted AGPS mode */
+#define LOC_GPS_CAPABILITY_MSA (1 << 2)
+/** GPS supports single-shot fixes */
+#define LOC_GPS_CAPABILITY_SINGLE_SHOT (1 << 3)
+/** GPS supports on demand time injection */
+#define LOC_GPS_CAPABILITY_ON_DEMAND_TIME (1 << 4)
+/** GPS supports Geofencing */
+#define LOC_GPS_CAPABILITY_GEOFENCING (1 << 5)
+/** GPS supports Measurements. */
+#define LOC_GPS_CAPABILITY_MEASUREMENTS (1 << 6)
+/** GPS supports Navigation Messages */
+#define LOC_GPS_CAPABILITY_NAV_MESSAGES (1 << 7)
+
+/**
+ * Flags used to specify which aiding data to delete when calling
+ * delete_aiding_data().
+ */
+typedef uint16_t LocGpsAidingData;
+/* IMPORTANT: Note that the following values must match
+ * constants in GpsLocationProvider.java. */
+#define LOC_GPS_DELETE_EPHEMERIS 0x0001
+#define LOC_GPS_DELETE_ALMANAC 0x0002
+#define LOC_GPS_DELETE_POSITION 0x0004
+#define LOC_GPS_DELETE_TIME 0x0008
+#define LOC_GPS_DELETE_IONO 0x0010
+#define LOC_GPS_DELETE_UTC 0x0020
+#define LOC_GPS_DELETE_HEALTH 0x0040
+#define LOC_GPS_DELETE_SVDIR 0x0080
+#define LOC_GPS_DELETE_SVSTEER 0x0100
+#define LOC_GPS_DELETE_SADATA 0x0200
+#define LOC_GPS_DELETE_RTI 0x0400
+#define LOC_GPS_DELETE_MB_DATA 0x0800
+#define LOC_GPS_DELETE_CELLDB_INFO 0x8000
+#define LOC_GPS_DELETE_ALL 0xFFFF
+
+/** AGPS type */
+typedef uint16_t LocAGpsType;
+#define LOC_AGPS_TYPE_ANY 0
+#define LOC_AGPS_TYPE_SUPL 1
+#define LOC_AGPS_TYPE_C2K 2
+#define LOC_AGPS_TYPE_WWAN_ANY 3
+#define LOC_AGPS_TYPE_WIFI 4
+#define LOC_AGPS_TYPE_SUPL_ES 5
+
+typedef uint16_t LocAGpsSetIDType;
+#define LOC_AGPS_SETID_TYPE_NONE 0
+#define LOC_AGPS_SETID_TYPE_IMSI 1
+#define LOC_AGPS_SETID_TYPE_MSISDN 2
+
+typedef uint16_t LocApnIpType;
+#define LOC_APN_IP_INVALID 0
+#define LOC_APN_IP_IPV4 1
+#define LOC_APN_IP_IPV6 2
+#define LOC_APN_IP_IPV4V6 3
+
+/**
+ * String length constants
+ */
+#define LOC_GPS_NI_SHORT_STRING_MAXLEN 256
+#define LOC_GPS_NI_LONG_STRING_MAXLEN 2048
+
+/**
+ * LocGpsNiType constants
+ */
+typedef uint32_t LocGpsNiType;
+#define LOC_GPS_NI_TYPE_VOICE 1
+#define LOC_GPS_NI_TYPE_UMTS_SUPL 2
+#define LOC_GPS_NI_TYPE_UMTS_CTRL_PLANE 3
+/*Emergency SUPL*/
+#define LOC_GPS_NI_TYPE_EMERGENCY_SUPL 4
+
+/**
+ * LocGpsNiNotifyFlags constants
+ */
+typedef uint32_t LocGpsNiNotifyFlags;
+/** NI requires notification */
+#define LOC_GPS_NI_NEED_NOTIFY 0x0001
+/** NI requires verification */
+#define LOC_GPS_NI_NEED_VERIFY 0x0002
+/** NI requires privacy override, no notification/minimal trace */
+#define LOC_GPS_NI_PRIVACY_OVERRIDE 0x0004
+
+/**
+ * GPS NI responses, used to define the response in
+ * NI structures
+ */
+typedef int LocGpsUserResponseType;
+#define LOC_GPS_NI_RESPONSE_ACCEPT 1
+#define LOC_GPS_NI_RESPONSE_DENY 2
+#define LOC_GPS_NI_RESPONSE_NORESP 3
+
+/**
+ * NI data encoding scheme
+ */
+typedef int LocGpsNiEncodingType;
+#define LOC_GPS_ENC_NONE 0
+#define LOC_GPS_ENC_SUPL_GSM_DEFAULT 1
+#define LOC_GPS_ENC_SUPL_UTF8 2
+#define LOC_GPS_ENC_SUPL_UCS2 3
+#define LOC_GPS_ENC_UNKNOWN -1
+
+/** AGPS status event values. */
+typedef uint8_t LocAGpsStatusValue;
+/** GPS requests data connection for AGPS. */
+#define LOC_GPS_REQUEST_AGPS_DATA_CONN 1
+/** GPS releases the AGPS data connection. */
+#define LOC_GPS_RELEASE_AGPS_DATA_CONN 2
+/** AGPS data connection initiated */
+#define LOC_GPS_AGPS_DATA_CONNECTED 3
+/** AGPS data connection completed */
+#define LOC_GPS_AGPS_DATA_CONN_DONE 4
+/** AGPS data connection failed */
+#define LOC_GPS_AGPS_DATA_CONN_FAILED 5
+
+typedef uint16_t LocAGpsRefLocationType;
+#define LOC_AGPS_REF_LOCATION_TYPE_GSM_CELLID 1
+#define LOC_AGPS_REF_LOCATION_TYPE_UMTS_CELLID 2
+#define LOC_AGPS_REF_LOCATION_TYPE_MAC 3
+#define LOC_AGPS_REF_LOCATION_TYPE_LTE_CELLID 4
+
+/* Deprecated, to be removed in the next Android release. */
+#define LOC_AGPS_REG_LOCATION_TYPE_MAC 3
+
+/** Network types for update_network_state "type" parameter */
+#define LOC_AGPS_RIL_NETWORK_TYPE_MOBILE 0
+#define LOC_AGPS_RIL_NETWORK_TYPE_WIFI 1
+#define LOC_AGPS_RIL_NETWORK_TYPE_MOBILE_MMS 2
+#define LOC_AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL 3
+#define LOC_AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN 4
+#define LOC_AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5
+#define LOC_AGPS_RIL_NETWORK_TTYPE_WIMAX 6
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t LocGpsClockFlags;
+#define LOC_GPS_CLOCK_HAS_LEAP_SECOND (1<<0)
+#define LOC_GPS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+#define LOC_GPS_CLOCK_HAS_FULL_BIAS (1<<2)
+#define LOC_GPS_CLOCK_HAS_BIAS (1<<3)
+#define LOC_GPS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+#define LOC_GPS_CLOCK_HAS_DRIFT (1<<5)
+#define LOC_GPS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/**
+ * Flags to indicate what fields in LocGnssClock are valid.
+ */
+typedef uint16_t LocGnssClockFlags;
+/** A valid 'leap second' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_LEAP_SECOND (1<<0)
+/** A valid 'time uncertainty' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_TIME_UNCERTAINTY (1<<1)
+/** A valid 'full bias' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_FULL_BIAS (1<<2)
+/** A valid 'bias' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_BIAS (1<<3)
+/** A valid 'bias uncertainty' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY (1<<4)
+/** A valid 'drift' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_DRIFT (1<<5)
+/** A valid 'drift uncertainty' is stored in the data structure. */
+#define LOC_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY (1<<6)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t LocGpsClockType;
+#define LOC_GPS_CLOCK_TYPE_UNKNOWN 0
+#define LOC_GPS_CLOCK_TYPE_LOCAL_HW_TIME 1
+#define LOC_GPS_CLOCK_TYPE_GPS_TIME 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint32_t LocGpsMeasurementFlags;
+#define LOC_GPS_MEASUREMENT_HAS_SNR (1<<0)
+#define LOC_GPS_MEASUREMENT_HAS_ELEVATION (1<<1)
+#define LOC_GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY (1<<2)
+#define LOC_GPS_MEASUREMENT_HAS_AZIMUTH (1<<3)
+#define LOC_GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY (1<<4)
+#define LOC_GPS_MEASUREMENT_HAS_PSEUDORANGE (1<<5)
+#define LOC_GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY (1<<6)
+#define LOC_GPS_MEASUREMENT_HAS_CODE_PHASE (1<<7)
+#define LOC_GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY (1<<8)
+#define LOC_GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+#define LOC_GPS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+#define LOC_GPS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+#define LOC_GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+#define LOC_GPS_MEASUREMENT_HAS_BIT_NUMBER (1<<13)
+#define LOC_GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT (1<<14)
+#define LOC_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT (1<<15)
+#define LOC_GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY (1<<16)
+#define LOC_GPS_MEASUREMENT_HAS_USED_IN_FIX (1<<17)
+#define LOC_GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE (1<<18)
+
+/**
+ * Flags to indicate what fields in LocGnssMeasurement are valid.
+ */
+typedef uint32_t LocGnssMeasurementFlags;
+/** A valid 'snr' is stored in the data structure. */
+#define LOC_GNSS_MEASUREMENT_HAS_SNR (1<<0)
+/** A valid 'carrier frequency' is stored in the data structure. */
+#define LOC_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY (1<<9)
+/** A valid 'carrier cycles' is stored in the data structure. */
+#define LOC_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES (1<<10)
+/** A valid 'carrier phase' is stored in the data structure. */
+#define LOC_GNSS_MEASUREMENT_HAS_CARRIER_PHASE (1<<11)
+/** A valid 'carrier phase uncertainty' is stored in the data structure. */
+#define LOC_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY (1<<12)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t LocGpsLossOfLock;
+#define LOC_GPS_LOSS_OF_LOCK_UNKNOWN 0
+#define LOC_GPS_LOSS_OF_LOCK_OK 1
+#define LOC_GPS_LOSS_OF_LOCK_CYCLE_SLIP 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. Use LocGnssMultipathIndicator instead.
+ */
+typedef uint8_t LocGpsMultipathIndicator;
+#define LOC_GPS_MULTIPATH_INDICATOR_UNKNOWN 0
+#define LOC_GPS_MULTIPATH_INDICATOR_DETECTED 1
+#define LOC_GPS_MULTIPATH_INDICATOR_NOT_USED 2
+
+/**
+ * Enumeration of available values for the GNSS Measurement's multipath
+ * indicator.
+ */
+typedef uint8_t LocGnssMultipathIndicator;
+/** The indicator is not available or unknown. */
+#define LOC_GNSS_MULTIPATH_INDICATOR_UNKNOWN 0
+/** The measurement is indicated to be affected by multipath. */
+#define LOC_GNSS_MULTIPATH_INDICATOR_PRESENT 1
+/** The measurement is indicated to be not affected by multipath. */
+#define LOC_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT 2
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t LocGpsMeasurementState;
+#define LOC_GPS_MEASUREMENT_STATE_UNKNOWN 0
+#define LOC_GPS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define LOC_GPS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define LOC_GPS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define LOC_GPS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define LOC_GPS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+
+/**
+ * Flags indicating the GNSS measurement state.
+ *
+ * The expected behavior here is for GPS HAL to set all the flags that applies.
+ * For example, if the state for a satellite is only C/A code locked and bit
+ * synchronized, and there is still millisecond ambiguity, the state should be
+ * set as:
+ *
+ * LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK | LOC_GNSS_MEASUREMENT_STATE_BIT_SYNC |
+ * LOC_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS
+ *
+ * If GNSS is still searching for a satellite, the corresponding state should be
+ * set to LOC_GNSS_MEASUREMENT_STATE_UNKNOWN(0).
+ */
+typedef uint32_t LocGnssMeasurementState;
+#define LOC_GNSS_MEASUREMENT_STATE_UNKNOWN 0
+#define LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK (1<<0)
+#define LOC_GNSS_MEASUREMENT_STATE_BIT_SYNC (1<<1)
+#define LOC_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC (1<<2)
+#define LOC_GNSS_MEASUREMENT_STATE_TOW_DECODED (1<<3)
+#define LOC_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS (1<<4)
+#define LOC_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC (1<<5)
+#define LOC_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC (1<<6)
+#define LOC_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED (1<<7)
+#define LOC_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC (1<<8)
+#define LOC_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC (1<<9)
+#define LOC_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK (1<<10)
+#define LOC_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK (1<<11)
+#define LOC_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC (1<<12)
+#define LOC_GNSS_MEASUREMENT_STATE_SBAS_SYNC (1<<13)
+
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint16_t LocGpsAccumulatedDeltaRangeState;
+#define LOC_GPS_ADR_STATE_UNKNOWN 0
+#define LOC_GPS_ADR_STATE_VALID (1<<0)
+#define LOC_GPS_ADR_STATE_RESET (1<<1)
+#define LOC_GPS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+/**
+ * Flags indicating the Accumulated Delta Range's states.
+ */
+typedef uint16_t LocGnssAccumulatedDeltaRangeState;
+#define LOC_GNSS_ADR_STATE_UNKNOWN 0
+#define LOC_GNSS_ADR_STATE_VALID (1<<0)
+#define LOC_GNSS_ADR_STATE_RESET (1<<1)
+#define LOC_GNSS_ADR_STATE_CYCLE_SLIP (1<<2)
+
+#if 0
+/* The following typedef together with its constants below are deprecated, and
+ * will be removed in the next release. */
+typedef uint8_t GpsNavigationMessageType;
+#define GPS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+#define GPS_NAVIGATION_MESSAGE_TYPE_L1CA 1
+#define GPS_NAVIGATION_MESSAGE_TYPE_L2CNAV 2
+#define GPS_NAVIGATION_MESSAGE_TYPE_L5CNAV 3
+#define GPS_NAVIGATION_MESSAGE_TYPE_CNAV2 4
+
+/**
+ * Enumeration of available values to indicate the GNSS Navigation message
+ * types.
+ *
+ * For convenience, first byte is the LocGnssConstellationType on which that signal
+ * is typically transmitted
+ */
+typedef int16_t GnssNavigationMessageType;
+
+#define GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN 0
+/** GPS L1 C/A message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L1CA 0x0101
+/** GPS L2-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L2CNAV 0x0102
+/** GPS L5-CNAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_L5CNAV 0x0103
+/** GPS CNAV-2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GPS_CNAV2 0x0104
+/** Glonass L1 CA message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GLO_L1CA 0x0301
+/** Beidou D1 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D1 0x0501
+/** Beidou D2 message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_BDS_D2 0x0502
+/** Galileo I/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_I 0x0601
+/** Galileo F/NAV message contained in the structure. */
+#define GNSS_NAVIGATION_MESSAGE_TYPE_GAL_F 0x0602
+
+/**
+ * Status of Navigation Message
+ * When a message is received properly without any parity error in its navigation words, the
+ * status should be set to NAV_MESSAGE_STATUS_PARITY_PASSED. But if a message is received
+ * with words that failed parity check, but GPS is able to correct those words, the status
+ * should be set to NAV_MESSAGE_STATUS_PARITY_REBUILT.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+typedef uint16_t NavigationMessageStatus;
+#define NAV_MESSAGE_STATUS_UNKNOWN 0
+#define NAV_MESSAGE_STATUS_PARITY_PASSED (1<<0)
+#define NAV_MESSAGE_STATUS_PARITY_REBUILT (1<<1)
+
+/* This constant is deprecated, and will be removed in the next release. */
+#define NAV_MESSAGE_STATUS_UNKONW 0
+#endif
+
+/**
+ * Flags that indicate information about the satellite
+ */
+typedef uint8_t LocGnssSvFlags;
+#define LOC_GNSS_SV_FLAGS_NONE 0
+#define LOC_GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA (1 << 0)
+#define LOC_GNSS_SV_FLAGS_HAS_ALMANAC_DATA (1 << 1)
+#define LOC_GNSS_SV_FLAGS_USED_IN_FIX (1 << 2)
+
+/**
+ * Constellation type of LocGnssSvInfo
+ */
+typedef uint8_t LocGnssConstellationType;
+#define LOC_GNSS_CONSTELLATION_UNKNOWN 0
+#define LOC_GNSS_CONSTELLATION_GPS 1
+#define LOC_GNSS_CONSTELLATION_SBAS 2
+#define LOC_GNSS_CONSTELLATION_GLONASS 3
+#define LOC_GNSS_CONSTELLATION_QZSS 4
+#define LOC_GNSS_CONSTELLATION_BEIDOU 5
+#define LOC_GNSS_CONSTELLATION_GALILEO 6
+
+/**
+ * Name for the GPS XTRA interface.
+ */
+#define LOC_GPS_XTRA_INTERFACE "gps-xtra"
+
+/**
+ * Name for the GPS DEBUG interface.
+ */
+#define LOC_GPS_DEBUG_INTERFACE "gps-debug"
+
+/**
+ * Name for the AGPS interface.
+ */
+
+#define LOC_AGPS_INTERFACE "agps"
+
+/**
+ * Name of the Supl Certificate interface.
+ */
+#define LOC_SUPL_CERTIFICATE_INTERFACE "supl-certificate"
+
+/**
+ * Name for NI interface
+ */
+#define LOC_GPS_NI_INTERFACE "gps-ni"
+
+/**
+ * Name for the AGPS-RIL interface.
+ */
+#define LOC_AGPS_RIL_INTERFACE "agps_ril"
+
+/**
+ * Name for the GPS_Geofencing interface.
+ */
+#define LOC_GPS_GEOFENCING_INTERFACE "gps_geofencing"
+
+/**
+ * Name of the GPS Measurements interface.
+ */
+#define LOC_GPS_MEASUREMENT_INTERFACE "gps_measurement"
+
+/**
+ * Name of the GPS navigation message interface.
+ */
+#define LOC_GPS_NAVIGATION_MESSAGE_INTERFACE "gps_navigation_message"
+
+/**
+ * Name of the GNSS/GPS configuration interface.
+ */
+#define LOC_GNSS_CONFIGURATION_INTERFACE "gnss_configuration"
+
+/** Represents a location. */
+typedef struct {
+ /** set to sizeof(LocGpsLocation) */
+ uint32_t size;
+ /** Contains LocGpsLocationFlags bits. */
+ uint16_t flags;
+ /** The spoof mask */
+ LocGpsSpoofMask spoof_mask;
+ /** Represents latitude in degrees. */
+ double latitude;
+ /** Represents longitude in degrees. */
+ double longitude;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid.
+ */
+ double altitude;
+ /** Represents horizontal speed in meters per second. */
+ float speed;
+ /** Represents heading in degrees. */
+ float bearing;
+ /** Represents expected accuracy in meters. */
+ float accuracy;
+ /** Represents the expected vertical uncertainity in meters*/
+ float vertUncertainity;
+ /** Timestamp for the location fix. */
+ LocGpsUtcTime timestamp;
+ /** Elapsed RealTime in nanosends */
+ uint64_t elapsedRealTime;
+ /** Elapsed Real Time Uncertainty in nanosends */
+ uint64_t elapsedRealTimeUnc;
+} LocGpsLocation;
+
+/** Represents the status. */
+typedef struct {
+ /** set to sizeof(LocGpsStatus) */
+ size_t size;
+ LocGpsStatusValue status;
+} LocGpsStatus;
+
+/**
+ * Legacy struct to represents SV information.
+ * Deprecated, to be removed in the next Android release.
+ * Use LocGnssSvInfo instead.
+ */
+typedef struct {
+ /** set to sizeof(LocGpsSvInfo) */
+ size_t size;
+ /** Pseudo-random number for the SV. */
+ int prn;
+ /** Signal to noise ratio. */
+ float snr;
+ /** Elevation of SV in degrees. */
+ float elevation;
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+} LocGpsSvInfo;
+
+typedef struct {
+ /** set to sizeof(LocGnssSvInfo) */
+ size_t size;
+
+ /**
+ * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+ * distinction is made by looking at constellation field. Values should be
+ * in the range of:
+ *
+ * - GPS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6 as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * LOC_GNSS_CONSTELLATION_* constants
+ */
+ LocGnssConstellationType constellation;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ float c_n0_dbhz;
+
+ /** Elevation of SV in degrees. */
+ float elevation;
+
+ /** Azimuth of SV in degrees. */
+ float azimuth;
+
+ /**
+ * Contains additional data about the given SV. Value should be one of those
+ * LOC_GNSS_SV_FLAGS_* constants
+ */
+ LocGnssSvFlags flags;
+
+} LocGnssSvInfo;
+
+/**
+ * Legacy struct to represents SV status.
+ * Deprecated, to be removed in the next Android release.
+ * Use LocGnssSvStatus instead.
+ */
+typedef struct {
+ /** set to sizeof(LocGpsSvStatus) */
+ size_t size;
+ int num_svs;
+ LocGpsSvInfo sv_list[LOC_GPS_MAX_SVS];
+ uint32_t ephemeris_mask;
+ uint32_t almanac_mask;
+ uint32_t used_in_fix_mask;
+} LocGpsSvStatus;
+
+/**
+ * Represents SV status.
+ */
+typedef struct {
+ /** set to sizeof(LocGnssSvStatus) */
+ size_t size;
+
+ /** Number of GPS SVs currently visible, refers to the SVs stored in sv_list */
+ int num_svs;
+ /**
+ * Pointer to an array of SVs information for all GNSS constellations,
+ * except GPS, which is reported using sv_list
+ */
+ LocGnssSvInfo gnss_sv_list[LOC_GNSS_MAX_SVS];
+
+} LocGnssSvStatus;
+
+/* CellID for 2G, 3G and LTE, used in AGPS. */
+typedef struct {
+ LocAGpsRefLocationType type;
+ /** Mobile Country Code. */
+ uint16_t mcc;
+ /** Mobile Network Code .*/
+ uint16_t mnc;
+ /** Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+ * lac is populated with tac, to ensure that we don't break old clients that
+ * might rely in the old (wrong) behavior.
+ */
+ uint16_t lac;
+ /** Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+ uint32_t cid;
+ /** Tracking Area Code in LTE. */
+ uint16_t tac;
+ /** Physical Cell id in LTE (not used in 2G and 3G) */
+ uint16_t pcid;
+} LocAGpsRefLocationCellID;
+
+typedef struct {
+ uint8_t mac[6];
+} LocAGpsRefLocationMac;
+
+/** Represents ref locations */
+typedef struct {
+ LocAGpsRefLocationType type;
+ union {
+ LocAGpsRefLocationCellID cellID;
+ LocAGpsRefLocationMac mac;
+ } u;
+} LocAGpsRefLocation;
+
+/**
+ * Callback with location information. Can only be called from a thread created
+ * by create_thread_cb.
+ */
+typedef void (* loc_gps_location_callback)(LocGpsLocation* location);
+
+/**
+ * Callback with status information. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (* loc_gps_status_callback)(LocGpsStatus* status);
+/**
+ * Legacy callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * loc_gnss_sv_status_callback() instead.
+ */
+typedef void (* loc_gps_sv_status_callback)(LocGpsSvStatus* sv_info);
+
+/**
+ * Callback with SV status information.
+ * Can only be called from a thread created by create_thread_cb.
+ */
+typedef void (* loc_gnss_sv_status_callback)(LocGnssSvStatus* sv_info);
+
+/**
+ * Callback for reporting NMEA sentences. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* loc_gps_nmea_callback)(LocGpsUtcTime timestamp, const char* nmea, int length);
+
+/**
+ * Callback to inform framework of the GPS engine's capabilities. Capability
+ * parameter is a bit field of LOC_GPS_CAPABILITY_* flags.
+ */
+typedef void (* loc_gps_set_capabilities)(uint32_t capabilities);
+
+/**
+ * Callback utility for acquiring the GPS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GPS events.
+ */
+typedef void (* loc_gps_acquire_wakelock)();
+
+/** Callback utility for releasing the GPS wakelock. */
+typedef void (* loc_gps_release_wakelock)();
+
+/** Callback for requesting NTP time */
+typedef void (* loc_gps_request_utc_time)();
+
+/**
+ * Callback for creating a thread that can call into the Java framework code.
+ * This must be used to create any threads that report events up to the
+ * framework.
+ */
+typedef pthread_t (* loc_gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+/**
+ * Provides information about how new the underlying GPS/GNSS hardware and
+ * software is.
+ *
+ * This information will be available for Android Test Applications. If a GPS
+ * HAL does not provide this information, it will be considered "2015 or
+ * earlier".
+ *
+ * If a GPS HAL does provide this information, then newer years will need to
+ * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+ * LocGpsMeasurement support will be verified.
+ */
+typedef struct {
+ /** Set to sizeof(LocGnssSystemInfo) */
+ size_t size;
+ /* year in which the last update was made to the underlying hardware/firmware
+ * used to capture GNSS signals, e.g. 2016 */
+ uint16_t year_of_hw;
+} LocGnssSystemInfo;
+
+/**
+ * Callback to inform framework of the engine's hardware version information.
+ */
+typedef void (*loc_gnss_set_system_info)(const LocGnssSystemInfo* info);
+
+/** New GPS callback structure. */
+typedef struct {
+ /** set to sizeof(LocGpsCallbacks) */
+ size_t size;
+ loc_gps_location_callback location_cb;
+ loc_gps_status_callback status_cb;
+ loc_gps_sv_status_callback sv_status_cb;
+ loc_gps_nmea_callback nmea_cb;
+ loc_gps_set_capabilities set_capabilities_cb;
+ loc_gps_acquire_wakelock acquire_wakelock_cb;
+ loc_gps_release_wakelock release_wakelock_cb;
+ loc_gps_create_thread create_thread_cb;
+ loc_gps_request_utc_time request_utc_time_cb;
+
+ loc_gnss_set_system_info set_system_info_cb;
+ loc_gnss_sv_status_callback gnss_sv_status_cb;
+} LocGpsCallbacks;
+
+/** Represents the standard GPS interface. */
+typedef struct {
+ /** set to sizeof(LocGpsInterface) */
+ size_t size;
+ /**
+ * Opens the interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( LocGpsCallbacks* callbacks );
+
+ /** Starts navigating. */
+ int (*start)( void );
+
+ /** Stops navigating. */
+ int (*stop)( void );
+
+ /** Closes the interface. */
+ void (*cleanup)( void );
+
+ /** Injects the current time. */
+ int (*inject_time)(LocGpsUtcTime time, int64_t timeReference,
+ int uncertainty);
+
+ /**
+ * Injects current location from another location provider (typically cell
+ * ID). Latitude and longitude are measured in degrees expected accuracy is
+ * measured in meters
+ */
+ int (*inject_location)(double latitude, double longitude, float accuracy);
+
+ /**
+ * Specifies that the next call to start will not use the
+ * information defined in the flags. LOC_GPS_DELETE_ALL is passed for
+ * a cold start.
+ */
+ void (*delete_aiding_data)(LocGpsAidingData flags);
+
+ /**
+ * min_interval represents the time between fixes in milliseconds.
+ * preferred_accuracy represents the requested fix accuracy in meters.
+ * preferred_time represents the requested time to first fix in milliseconds.
+ *
+ * 'mode' parameter should be one of LOC_GPS_POSITION_MODE_MS_BASED
+ * or LOC_GPS_POSITION_MODE_STANDALONE.
+ * It is allowed by the platform (and it is recommended) to fallback to
+ * LOC_GPS_POSITION_MODE_MS_BASED if LOC_GPS_POSITION_MODE_MS_ASSISTED is passed in, and
+ * LOC_GPS_POSITION_MODE_MS_BASED is supported.
+ */
+ int (*set_position_mode)(LocGpsPositionMode mode, LocGpsPositionRecurrence recurrence,
+ uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
+
+ /** Get a pointer to extension information. */
+ const void* (*get_extension)(const char* name);
+} LocGpsInterface;
+
+/**
+ * Callback to request the client to download XTRA data. The client should
+ * download XTRA data and inject it by calling inject_xtra_data(). Can only be
+ * called from a thread created by create_thread_cb.
+ */
+typedef void (* loc_gps_xtra_download_request)();
+
+/** Callback structure for the XTRA interface. */
+typedef struct {
+ loc_gps_xtra_download_request download_request_cb;
+ loc_gps_create_thread create_thread_cb;
+} LocGpsXtraCallbacks;
+
+/** Extended interface for XTRA support. */
+typedef struct {
+ /** set to sizeof(LocGpsXtraInterface) */
+ size_t size;
+ /**
+ * Opens the XTRA interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ int (*init)( LocGpsXtraCallbacks* callbacks );
+ /** Injects XTRA data into the GPS. */
+ int (*inject_xtra_data)( char* data, int length );
+} LocGpsXtraInterface;
+
+#if 0
+/** Extended interface for DEBUG support. */
+typedef struct {
+ /** set to sizeof(LocGpsDebugInterface) */
+ size_t size;
+
+ /**
+ * This function should return any information that the native
+ * implementation wishes to include in a bugreport.
+ */
+ size_t (*get_internal_state)(char* buffer, size_t bufferSize);
+} LocGpsDebugInterface;
+#endif
+
+/*
+ * Represents the status of AGPS augmented to support IPv4 and IPv6.
+ */
+typedef struct {
+ /** set to sizeof(LocAGpsStatus) */
+ size_t size;
+
+ LocAGpsType type;
+ LocAGpsStatusValue status;
+
+ /**
+ * Must be set to a valid IPv4 address if the field 'addr' contains an IPv4
+ * address, or set to INADDR_NONE otherwise.
+ */
+ uint32_t ipaddr;
+
+ /**
+ * Must contain the IPv4 (AF_INET) or IPv6 (AF_INET6) address to report.
+ * Any other value of addr.ss_family will be rejected.
+ */
+ struct sockaddr_storage addr;
+} LocAGpsStatus;
+
+/**
+ * Callback with AGPS status information. Can only be called from a thread
+ * created by create_thread_cb.
+ */
+typedef void (* loc_agps_status_callback)(LocAGpsStatus* status);
+
+/** Callback structure for the AGPS interface. */
+typedef struct {
+ loc_agps_status_callback status_cb;
+ loc_gps_create_thread create_thread_cb;
+} LocAGpsCallbacks;
+
+/**
+ * Extended interface for AGPS support, it is augmented to enable to pass
+ * extra APN data.
+ */
+typedef struct {
+ /** set to sizeof(LocAGpsInterface) */
+ size_t size;
+
+ /**
+ * Opens the AGPS interface and provides the callback routines to the
+ * implementation of this interface.
+ */
+ void (*init)(LocAGpsCallbacks* callbacks);
+ /**
+ * Deprecated.
+ * If the HAL supports LocAGpsInterface_v2 this API will not be used, see
+ * data_conn_open_with_apn_ip_type for more information.
+ */
+ int (*data_conn_open)(const char* apn);
+ /**
+ * Notifies that the AGPS data connection has been closed.
+ */
+ int (*data_conn_closed)();
+ /**
+ * Notifies that a data connection is not available for AGPS.
+ */
+ int (*data_conn_failed)();
+ /**
+ * Sets the hostname and port for the AGPS server.
+ */
+ int (*set_server)(LocAGpsType type, const char* hostname, int port);
+
+ /**
+ * Notifies that a data connection is available and sets the name of the
+ * APN, and its IP type, to be used for SUPL connections.
+ */
+ int (*data_conn_open_with_apn_ip_type)(
+ const char* apn,
+ LocApnIpType apnIpType);
+} LocAGpsInterface;
+
+/** Error codes associated with certificate operations */
+#define LOC_AGPS_CERTIFICATE_OPERATION_SUCCESS 0
+#define LOC_AGPS_CERTIFICATE_ERROR_GENERIC -100
+#define LOC_AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES -101
+
+/** A data structure that represents an X.509 certificate using DER encoding */
+typedef struct {
+ size_t length;
+ u_char* data;
+} LocDerEncodedCertificate;
+
+/**
+ * A type definition for SHA1 Fingerprints used to identify X.509 Certificates
+ * The Fingerprint is a digest of the DER Certificate that uniquely identifies it.
+ */
+typedef struct {
+ u_char data[20];
+} LocSha1CertificateFingerprint;
+
+/** AGPS Interface to handle SUPL certificate operations */
+typedef struct {
+ /** set to sizeof(LocSuplCertificateInterface) */
+ size_t size;
+
+ /**
+ * Installs a set of Certificates used for SUPL connections to the AGPS server.
+ * If needed the HAL should find out internally any certificates that need to be removed to
+ * accommodate the certificates to install.
+ * The certificates installed represent a full set of valid certificates needed to connect to
+ * AGPS SUPL servers.
+ * The list of certificates is required, and all must be available at the same time, when trying
+ * to establish a connection with the AGPS Server.
+ *
+ * Parameters:
+ * certificates - A pointer to an array of DER encoded certificates that are need to be
+ * installed in the HAL.
+ * length - The number of certificates to install.
+ * Returns:
+ * LOC_AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully
+ * LOC_AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES if the HAL cannot store the number of
+ * certificates attempted to be installed, the state of the certificates stored should
+ * remain the same as before on this error case.
+ *
+ * IMPORTANT:
+ * If needed the HAL should find out internally the set of certificates that need to be
+ * removed to accommodate the certificates to install.
+ */
+ int (*install_certificates) ( const LocDerEncodedCertificate* certificates, size_t length );
+
+ /**
+ * Notifies the HAL that a list of certificates used for SUPL connections are revoked. It is
+ * expected that the given set of certificates is removed from the internal store of the HAL.
+ *
+ * Parameters:
+ * fingerprints - A pointer to an array of SHA1 Fingerprints to identify the set of
+ * certificates to revoke.
+ * length - The number of fingerprints provided.
+ * Returns:
+ * LOC_AGPS_CERTIFICATE_OPERATION_SUCCESS if the operation is completed successfully.
+ *
+ * IMPORTANT:
+ * If any of the certificates provided (through its fingerprint) is not known by the HAL,
+ * it should be ignored and continue revoking/deleting the rest of them.
+ */
+ int (*revoke_certificates) ( const LocSha1CertificateFingerprint* fingerprints, size_t length );
+} LocSuplCertificateInterface;
+
+/** Represents an NI request */
+typedef struct {
+ /** set to sizeof(LocGpsNiNotification) */
+ size_t size;
+
+ /**
+ * An ID generated by HAL to associate NI notifications and UI
+ * responses
+ */
+ int notification_id;
+
+ /**
+ * An NI type used to distinguish different categories of NI
+ * events, such as LOC_GPS_NI_TYPE_VOICE, LOC_GPS_NI_TYPE_UMTS_SUPL, ...
+ */
+ LocGpsNiType ni_type;
+
+ /**
+ * Notification/verification options, combinations of LocGpsNiNotifyFlags constants
+ */
+ LocGpsNiNotifyFlags notify_flags;
+
+ /**
+ * Timeout period to wait for user response.
+ * Set to 0 for no time out limit.
+ */
+ int timeout;
+
+ /**
+ * Default response when time out.
+ */
+ LocGpsUserResponseType default_response;
+
+ /**
+ * Requestor ID
+ */
+ char requestor_id[LOC_GPS_NI_SHORT_STRING_MAXLEN];
+
+ /**
+ * Notification message. It can also be used to store client_id in some cases
+ */
+ char text[LOC_GPS_NI_LONG_STRING_MAXLEN];
+
+ /**
+ * Client name decoding scheme
+ */
+ LocGpsNiEncodingType requestor_id_encoding;
+
+ /**
+ * Client name decoding scheme
+ */
+ LocGpsNiEncodingType text_encoding;
+
+ /**
+ * A pointer to extra data. Format:
+ * key_1 = value_1
+ * key_2 = value_2
+ */
+ char extras[LOC_GPS_NI_LONG_STRING_MAXLEN];
+
+} LocGpsNiNotification;
+
+/**
+ * Callback with NI notification. Can only be called from a thread created by
+ * create_thread_cb.
+ */
+typedef void (*loc_gps_ni_notify_callback)(LocGpsNiNotification *notification);
+
+/** GPS NI callback structure. */
+typedef struct
+{
+ /**
+ * Sends the notification request from HAL to GPSLocationProvider.
+ */
+ loc_gps_ni_notify_callback notify_cb;
+ loc_gps_create_thread create_thread_cb;
+} LocGpsNiCallbacks;
+
+/**
+ * Extended interface for Network-initiated (NI) support.
+ */
+typedef struct
+{
+ /** set to sizeof(LocGpsNiInterface) */
+ size_t size;
+
+ /** Registers the callbacks for HAL to use. */
+ void (*init) (LocGpsNiCallbacks *callbacks);
+
+ /** Sends a response to HAL. */
+ void (*respond) (int notif_id, LocGpsUserResponseType user_response);
+} LocGpsNiInterface;
+
+#define LOC_AGPS_RIL_REQUEST_SETID_IMSI (1<<0L)
+#define LOC_AGPS_RIL_REQUEST_SETID_MSISDN (1<<1L)
+
+#define LOC_AGPS_RIL_REQUEST_REFLOC_CELLID (1<<0L)
+#define LOC_AGPS_RIL_REQUEST_REFLOC_MAC (1<<1L)
+
+typedef void (*loc_agps_ril_request_set_id)(uint32_t flags);
+typedef void (*loc_agps_ril_request_ref_loc)(uint32_t flags);
+
+typedef struct {
+ loc_agps_ril_request_set_id request_setid;
+ loc_agps_ril_request_ref_loc request_refloc;
+ loc_gps_create_thread create_thread_cb;
+} LocAGpsRilCallbacks;
+
+/** Extended interface for AGPS_RIL support. */
+typedef struct {
+ /** set to sizeof(LocAGpsRilInterface) */
+ size_t size;
+ /**
+ * Opens the AGPS interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( LocAGpsRilCallbacks* callbacks );
+
+ /**
+ * Sets the reference location.
+ */
+ void (*set_ref_location) (const LocAGpsRefLocation *agps_reflocation, size_t sz_struct);
+ /**
+ * Sets the set ID.
+ */
+ void (*set_set_id) (LocAGpsSetIDType type, const char* setid);
+
+ /**
+ * Send network initiated message.
+ */
+ void (*ni_message) (uint8_t *msg, size_t len);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_state) (int connected, int type, int roaming, const char* extra_info);
+
+ /**
+ * Notify GPS of network status changes.
+ * These parameters match values in the android.net.NetworkInfo class.
+ */
+ void (*update_network_availability) (int avaiable, const char* apn);
+} LocAGpsRilInterface;
+
+/**
+ * GPS Geofence.
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter)
+ * ____________________________
+ * | Unknown (30 secs) |
+ * """"""""""""""""""""""""""""
+ * ^ | | ^
+ * UNCERTAIN| |ENTERED EXITED| |UNCERTAIN
+ * | v v |
+ * ________ EXITED _________
+ * | Inside | -----------> | Outside |
+ * | | <----------- | |
+ * """""""" ENTERED """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ * __________
+ * | c|
+ * | ___ | _______
+ * | |a| | | b |
+ * | """ | """""""
+ * | |
+ * """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GPS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition would be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition should be triggered. This "sufficient period of time"
+ * is defined by the parameter in the add_geofence_area API.
+ * In other words, Unknown state can be interpreted as a state in which the
+ * GPS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GPS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * should be triggered only for the transitions requested by the
+ * add_geofence_area call.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transistions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GPS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GPS system is unavailable, loc_gps_geofence_status_callback should be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback should be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GPS Geofence will just be a signal indicating what the GPS
+ * subsystem knows about the Geofence.
+ *
+ */
+#define LOC_GPS_GEOFENCE_ENTERED (1<<0L)
+#define LOC_GPS_GEOFENCE_EXITED (1<<1L)
+#define LOC_GPS_GEOFENCE_UNCERTAIN (1<<2L)
+
+#define LOC_GPS_GEOFENCE_UNAVAILABLE (1<<0L)
+#define LOC_GPS_GEOFENCE_AVAILABLE (1<<1L)
+
+#define LOC_GPS_GEOFENCE_OPERATION_SUCCESS 0
+#define LOC_GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES -100
+#define LOC_GPS_GEOFENCE_ERROR_ID_EXISTS -101
+#define LOC_GPS_GEOFENCE_ERROR_ID_UNKNOWN -102
+#define LOC_GPS_GEOFENCE_ERROR_INVALID_TRANSITION -103
+#define LOC_GPS_GEOFENCE_ERROR_GENERIC -149
+
+/**
+ * The callback associated with the geofence.
+ * Parameters:
+ * geofence_id - The id associated with the add_geofence_area.
+ * location - The current GPS location.
+ * transition - Can be one of LOC_GPS_GEOFENCE_ENTERED, LOC_GPS_GEOFENCE_EXITED,
+ * LOC_GPS_GEOFENCE_UNCERTAIN.
+ * timestamp - Timestamp when the transition was detected.
+ *
+ * The callback should only be called when the caller is interested in that
+ * particular transition. For instance, if the caller is interested only in
+ * ENTERED transition, then the callback should NOT be called with the EXITED
+ * transition.
+ *
+ * IMPORTANT: If a transition is triggered resulting in this callback, the GPS
+ * subsystem will wake up the application processor, if its in suspend state.
+ */
+typedef void (*loc_gps_geofence_transition_callback) (int32_t geofence_id, LocGpsLocation* location,
+ int32_t transition, LocGpsUtcTime timestamp);
+
+/**
+ * The callback associated with the availability of the GPS system for geofencing
+ * monitoring. If the GPS system determines that it cannot monitor geofences
+ * because of lack of reliability or unavailability of the GPS signals, it will
+ * call this callback with LOC_GPS_GEOFENCE_UNAVAILABLE parameter.
+ *
+ * Parameters:
+ * status - LOC_GPS_GEOFENCE_UNAVAILABLE or LOC_GPS_GEOFENCE_AVAILABLE.
+ * last_location - Last known location.
+ */
+typedef void (*loc_gps_geofence_status_callback) (int32_t status, LocGpsLocation* last_location);
+
+/**
+ * The callback associated with the add_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - LOC_GPS_GEOFENCE_OPERATION_SUCCESS
+ * LOC_GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES - geofence limit has been reached.
+ * LOC_GPS_GEOFENCE_ERROR_ID_EXISTS - geofence with id already exists
+ * LOC_GPS_GEOFENCE_ERROR_INVALID_TRANSITION - the monitorTransition contains an
+ * invalid transition
+ * LOC_GPS_GEOFENCE_ERROR_GENERIC - for other errors.
+ */
+typedef void (*loc_gps_geofence_add_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the remove_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - LOC_GPS_GEOFENCE_OPERATION_SUCCESS
+ * LOC_GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * LOC_GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*loc_gps_geofence_remove_callback) (int32_t geofence_id, int32_t status);
+
+
+/**
+ * The callback associated with the pause_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - LOC_GPS_GEOFENCE_OPERATION_SUCCESS
+ * LOC_GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * LOC_GPS_GEOFENCE_ERROR_INVALID_TRANSITION -
+ * when monitor_transitions is invalid
+ * LOC_GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*loc_gps_geofence_pause_callback) (int32_t geofence_id, int32_t status);
+
+/**
+ * The callback associated with the resume_geofence call.
+ *
+ * Parameter:
+ * geofence_id - Id of the geofence.
+ * status - LOC_GPS_GEOFENCE_OPERATION_SUCCESS
+ * LOC_GPS_GEOFENCE_ERROR_ID_UNKNOWN - for invalid id
+ * LOC_GPS_GEOFENCE_ERROR_GENERIC for others.
+ */
+typedef void (*loc_gps_geofence_resume_callback) (int32_t geofence_id, int32_t status);
+
+typedef struct {
+ loc_gps_geofence_transition_callback geofence_transition_callback;
+ loc_gps_geofence_status_callback geofence_status_callback;
+ loc_gps_geofence_add_callback geofence_add_callback;
+ loc_gps_geofence_remove_callback geofence_remove_callback;
+ loc_gps_geofence_pause_callback geofence_pause_callback;
+ loc_gps_geofence_resume_callback geofence_resume_callback;
+ loc_gps_create_thread create_thread_cb;
+} LocGpsGeofenceCallbacks;
+
+/** Extended interface for GPS_Geofencing support */
+typedef struct {
+ /** set to sizeof(LocGpsGeofencingInterface) */
+ size_t size;
+
+ /**
+ * Opens the geofence interface and provides the callback routines
+ * to the implementation of this interface.
+ */
+ void (*init)( LocGpsGeofenceCallbacks* callbacks );
+
+ /**
+ * Add a geofence area. This api currently supports circular geofences.
+ * Parameters:
+ * geofence_id - The id for the geofence. If a geofence with this id
+ * already exists, an error value (LOC_GPS_GEOFENCE_ERROR_ID_EXISTS)
+ * should be returned.
+ * latitude, longtitude, radius_meters - The lat, long and radius
+ * (in meters) for the geofence
+ * last_transition - The current state of the geofence. For example, if
+ * the system already knows that the user is inside the geofence,
+ * this will be set to LOC_GPS_GEOFENCE_ENTERED. In most cases, it
+ * will be LOC_GPS_GEOFENCE_UNCERTAIN.
+ * monitor_transition - Which transitions to monitor. Bitwise OR of
+ * LOC_GPS_GEOFENCE_ENTERED, LOC_GPS_GEOFENCE_EXITED and
+ * LOC_GPS_GEOFENCE_UNCERTAIN.
+ * notification_responsiveness_ms - Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if set
+ * to 1000 millseconds with LOC_GPS_GEOFENCE_ENTERED, the callback
+ * should be called 1000 milliseconds within entering the geofence.
+ * This parameter is defined in milliseconds.
+ * NOTE: This is not to be confused with the rate that the GPS is
+ * polled at. It is acceptable to dynamically vary the rate of
+ * sampling the GPS for power-saving reasons; thus the rate of
+ * sampling may be faster or slower than this.
+ * unknown_timer_ms - The time limit after which the UNCERTAIN transition
+ * should be triggered. This parameter is defined in milliseconds.
+ * See above for a detailed explanation.
+ */
+ void (*add_geofence_area) (int32_t geofence_id, double latitude, double longitude,
+ double radius_meters, int last_transition, int monitor_transitions,
+ int notification_responsiveness_ms, int unknown_timer_ms);
+
+ /**
+ * Pause monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ */
+ void (*pause_geofence) (int32_t geofence_id);
+
+ /**
+ * Resume monitoring a particular geofence.
+ * Parameters:
+ * geofence_id - The id for the geofence.
+ * monitor_transitions - Which transitions to monitor. Bitwise OR of
+ * LOC_GPS_GEOFENCE_ENTERED, LOC_GPS_GEOFENCE_EXITED and
+ * LOC_GPS_GEOFENCE_UNCERTAIN.
+ * This supersedes the value associated provided in the
+ * add_geofence_area call.
+ */
+ void (*resume_geofence) (int32_t geofence_id, int monitor_transitions);
+
+ /**
+ * Remove a geofence area. After the function returns, no notifications
+ * should be sent.
+ * Parameter:
+ * geofence_id - The id for the geofence.
+ */
+ void (*remove_geofence_area) (int32_t geofence_id);
+} LocGpsGeofencingInterface;
+
+/**
+ * Legacy struct to represent an estimate of the GPS clock time.
+ * Deprecated, to be removed in the next Android release.
+ * Use LocGnssClock instead.
+ */
+typedef struct {
+ /** set to sizeof(LocGpsClock) */
+ size_t size;
+ LocGpsClockFlags flags;
+ int16_t leap_second;
+ LocGpsClockType type;
+ int64_t time_ns;
+ double time_uncertainty_ns;
+ int64_t full_bias_ns;
+ double bias_ns;
+ double bias_uncertainty_ns;
+ double drift_nsps;
+ double drift_uncertainty_nsps;
+} LocGpsClock;
+
+/**
+ * Represents an estimate of the GPS clock time.
+ */
+typedef struct {
+ /** set to sizeof(LocGnssClock) */
+ size_t size;
+
+ /**
+ * A set of flags indicating the validity of the fields in this data
+ * structure.
+ */
+ LocGnssClockFlags flags;
+
+ /**
+ * Leap second data.
+ * The sign of the value is defined by the following equation:
+ * utc_time_ns = time_ns - (full_bias_ns + bias_ns) - leap_second *
+ * 1,000,000,000
+ *
+ * If the data is available 'flags' must contain LOC_GNSS_CLOCK_HAS_LEAP_SECOND.
+ */
+ int16_t leap_second;
+
+ /**
+ * The GNSS receiver internal clock value. This is the local hardware clock
+ * value.
+ *
+ * For local hardware clock, this value is expected to be monotonically
+ * increasing while the hardware clock remains power on. (For the case of a
+ * HW clock that is not continuously on, see the
+ * hw_clock_discontinuity_count field). The receiver's estimate of GPS time
+ * can be derived by substracting the sum of full_bias_ns and bias_ns (when
+ * available) from this value.
+ *
+ * This GPS time is expected to be the best estimate of current GPS time
+ * that GNSS receiver can achieve.
+ *
+ * Sub-nanosecond accuracy can be provided by means of the 'bias_ns' field.
+ * The value contains the 'time uncertainty' in it.
+ *
+ * This field is mandatory.
+ */
+ int64_t time_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available, 'flags' must contain
+ * LOC_GNSS_CLOCK_HAS_TIME_UNCERTAINTY. This value is effectively zero (it is
+ * the reference local clock, by which all other times and time
+ * uncertainties are measured.) (And thus this field can be not provided,
+ * per LOC_GNSS_CLOCK_HAS_TIME_UNCERTAINTY flag, or provided & set to 0.)
+ */
+ double time_uncertainty_ns;
+
+ /**
+ * The difference between hardware clock ('time' field) inside GPS receiver
+ * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+ *
+ * The sign of the value is defined by the following equation:
+ * local estimate of GPS time = time_ns - (full_bias_ns + bias_ns)
+ *
+ * This value is mandatory if the receiver has estimated GPS time. If the
+ * computed time is for a non-GPS constellation, the time offset of that
+ * constellation to GPS has to be applied to fill this value. The error
+ * estimate for the sum of this and the bias_ns is the bias_uncertainty_ns,
+ * and the caller is responsible for using this uncertainty (it can be very
+ * large before the GPS time has been solved for.) If the data is available
+ * 'flags' must contain LOC_GNSS_CLOCK_HAS_FULL_BIAS.
+ */
+ int64_t full_bias_ns;
+
+ /**
+ * Sub-nanosecond bias.
+ * The error estimate for the sum of this and the full_bias_ns is the
+ * bias_uncertainty_ns
+ *
+ * If the data is available 'flags' must contain LOC_GNSS_CLOCK_HAS_BIAS. If GPS
+ * has computed a position fix. This value is mandatory if the receiver has
+ * estimated GPS time.
+ */
+ double bias_ns;
+
+ /**
+ * 1-Sigma uncertainty associated with the local estimate of GPS time (clock
+ * bias) in nanoseconds. The uncertainty is represented as an absolute
+ * (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * LOC_GNSS_CLOCK_HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+ * has estimated GPS time.
+ */
+ double bias_uncertainty_ns;
+
+ /**
+ * The clock's drift in nanoseconds (per second).
+ *
+ * A positive value means that the frequency is higher than the nominal
+ * frequency, and that the (full_bias_ns + bias_ns) is growing more positive
+ * over time.
+ *
+ * The value contains the 'drift uncertainty' in it.
+ * If the data is available 'flags' must contain LOC_GNSS_CLOCK_HAS_DRIFT.
+ *
+ * This value is mandatory if the receiver has estimated GNSS time
+ */
+ double drift_nsps;
+
+ /**
+ * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per second).
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * If the data is available 'flags' must contain
+ * LOC_GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY. If GPS has computed a position fix this
+ * field is mandatory and must be populated.
+ */
+ double drift_uncertainty_nsps;
+
+ /**
+ * When there are any discontinuities in the HW clock, this field is
+ * mandatory.
+ *
+ * A "discontinuity" is meant to cover the case of a switch from one source
+ * of clock to another. A single free-running crystal oscillator (XO)
+ * should generally not have any discontinuities, and this can be set and
+ * left at 0.
+ *
+ * If, however, the time_ns value (HW clock) is derived from a composite of
+ * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+ * restarted, then this value shall be incremented each time a discontinuity
+ * occurs. (E.g. this value may start at zero at device boot-up and
+ * increment each time there is a change in clock continuity. In the
+ * unlikely event that this value reaches full scale, rollover (not
+ * clamping) is required, such that this value continues to change, during
+ * subsequent discontinuity events.)
+ *
+ * While this number stays the same, between LocGnssClock reports, it can be
+ * safely assumed that the time_ns value has been running continuously, e.g.
+ * derived from a single, high quality clock (XO like, or better, that's
+ * typically used during continuous GNSS signal sampling.)
+ *
+ * It is expected, esp. during periods where there are few GNSS signals
+ * available, that the HW clock be discontinuity-free as long as possible,
+ * as this avoids the need to use (waste) a GNSS measurement to fully
+ * re-solve for the GPS clock bias and drift, when using the accompanying
+ * measurements, from consecutive LocGnssData reports.
+ */
+ uint32_t hw_clock_discontinuity_count;
+
+} LocGnssClock;
+
+/**
+ * Legacy struct to represent a GPS Measurement, it contains raw and computed
+ * information.
+ * Deprecated, to be removed in the next Android release.
+ * Use LocGnssMeasurement instead.
+ */
+typedef struct {
+ /** set to sizeof(LocGpsMeasurement) */
+ size_t size;
+ LocGpsMeasurementFlags flags;
+ int8_t prn;
+ double time_offset_ns;
+ LocGpsMeasurementState state;
+ int64_t received_gps_tow_ns;
+ int64_t received_gps_tow_uncertainty_ns;
+ double c_n0_dbhz;
+ double pseudorange_rate_mps;
+ double pseudorange_rate_uncertainty_mps;
+ LocGpsAccumulatedDeltaRangeState accumulated_delta_range_state;
+ double accumulated_delta_range_m;
+ double accumulated_delta_range_uncertainty_m;
+ double pseudorange_m;
+ double pseudorange_uncertainty_m;
+ double code_phase_chips;
+ double code_phase_uncertainty_chips;
+ float carrier_frequency_hz;
+ int64_t carrier_cycles;
+ double carrier_phase;
+ double carrier_phase_uncertainty;
+ LocGpsLossOfLock loss_of_lock;
+ int32_t bit_number;
+ int16_t time_from_last_bit_ms;
+ double doppler_shift_hz;
+ double doppler_shift_uncertainty_hz;
+ LocGpsMultipathIndicator multipath_indicator;
+ double snr_db;
+ double elevation_deg;
+ double elevation_uncertainty_deg;
+ double azimuth_deg;
+ double azimuth_uncertainty_deg;
+ bool used_in_fix;
+} LocGpsMeasurement;
+
+/**
+ * Represents a GNSS Measurement, it contains raw and computed information.
+ *
+ * Independence - All signal measurement information (e.g. sv_time,
+ * pseudorange_rate, multipath_indicator) reported in this struct should be
+ * based on GNSS signal measurements only. You may not synthesize measurements
+ * by calculating or reporting expected measurements based on known or estimated
+ * position, velocity, or time.
+ */
+typedef struct {
+ /** set to sizeof(LocGnssMeasurement) */
+ size_t size;
+
+ /** A set of flags indicating the validity of the fields in this data structure. */
+ LocGnssMeasurementFlags flags;
+
+ /**
+ * Satellite vehicle ID number, as defined in LocGnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * Defines the constellation of the given SV. Value should be one of those
+ * LOC_GNSS_CONSTELLATION_* constants
+ */
+ LocGnssConstellationType constellation;
+
+ /**
+ * Time offset at which the measurement was taken in nanoseconds.
+ * The reference receiver's time is specified by LocGpsData::clock::time_ns and should be
+ * interpreted in the same way as indicated by LocGpsClock::type.
+ *
+ * The sign of time_offset_ns is given by the following equation:
+ * measurement time = LocGpsClock::time_ns + time_offset_ns
+ *
+ * It provides an individual time-stamp for the measurement, and allows sub-nanosecond accuracy.
+ * This is a mandatory value.
+ */
+ double time_offset_ns;
+
+ /**
+ * Per satellite sync state. It represents the current sync state for the associated satellite.
+ * Based on the sync state, the 'received GPS tow' field should be interpreted accordingly.
+ *
+ * This is a mandatory value.
+ */
+ LocGnssMeasurementState state;
+
+ /**
+ * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+ * Ensure that this field is independent (see comment at top of
+ * LocGnssMeasurement struct.)
+ *
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : LOC_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : LOC_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : LOC_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : LOC_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * LOC_GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != LOC_GNSS_MEASUREMENT_STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : LOC_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : LOC_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : LOC_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : LOC_GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : LOC_GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : LOC_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Bit sync (D2): [ 0 2ms ] : LOC_GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1): [ 0 20ms ] : LOC_GNSS_MEASUREMENT_STATE_BIT_SYNC is set
+ * Subframe (D2): [ 0 0.6s ] : LOC_GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1): [ 0 6s ] : LOC_GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : LOC_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : LOC_GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock: [ 0 100ms ] :
+ * LOC_GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : LOC_GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week: [ 0 1week ] : LOC_GNSS_MEASUREMENT_STATE_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite,
+ * valid range for this field can be:
+ * Searching : [ 0 ] : LOC_GNSS_MEASUREMENT_STATE_UNKNOWN
+ * C/A code lock: [ 0 1ms ] : LOC_GNSS_MEASUREMENT_STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : LOC_GNSS_MEASUREMENT_STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : LOC_GNSS_MEASUREMENT_STATE_SBAS_SYNC is set
+ */
+ int64_t received_sv_time_in_ns;
+
+ /**
+ * 1-Sigma uncertainty of the Received GPS Time-of-Week in nanoseconds.
+ *
+ * This value must be populated if 'state' != LOC_GPS_MEASUREMENT_STATE_UNKNOWN.
+ */
+ int64_t received_sv_time_uncertainty_in_ns;
+
+ /**
+ * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+ * It contains the measured C/N0 value for the signal at the antenna port.
+ *
+ * This is a mandatory value.
+ */
+ double c_n0_dbhz;
+
+ /**
+ * Pseudorange rate at the timestamp in m/s. The correction of a given
+ * Pseudorange Rate value includes corrections for receiver and satellite
+ * clock frequency errors. Ensure that this field is independent (see
+ * comment at top of LocGnssMeasurement struct.)
+ *
+ * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and provide LocGpsClock's
+ * 'drift' field as well (When providing the uncorrected pseudorange rate, do not apply the
+ * corrections described above.)
+ *
+ * The value includes the 'pseudorange rate uncertainty' in it.
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler
+ * shift' is given by the equation:
+ * pseudorange rate = -k * doppler shift (where k is a constant)
+ *
+ * This should be the most accurate pseudorange rate available, based on
+ * fresh signal measurements from this channel.
+ *
+ * It is mandatory that this value be provided at typical carrier phase PRR
+ * quality (few cm/sec per second of uncertainty, or better) - when signals
+ * are sufficiently strong & stable, e.g. signals from a GPS simulator at >=
+ * 35 dB-Hz.
+ */
+ double pseudorange_rate_mps;
+
+ /**
+ * 1-Sigma uncertainty of the pseudorange_rate_mps.
+ * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * This is a mandatory value.
+ */
+ double pseudorange_rate_uncertainty_mps;
+
+ /**
+ * Accumulated delta range's state. It indicates whether ADR is reset or there is a cycle slip
+ * (indicating loss of lock).
+ *
+ * This is a mandatory value.
+ */
+ LocGnssAccumulatedDeltaRangeState accumulated_delta_range_state;
+
+ /**
+ * Accumulated delta range since the last channel reset in meters.
+ * A positive value indicates that the SV is moving away from the receiver.
+ *
+ * The sign of the 'accumulated delta range' and its relation to the sign of 'carrier phase'
+ * is given by the equation:
+ * accumulated delta range = -k * carrier phase (where k is a constant)
+ *
+ * This value must be populated if 'accumulated delta range state' != LOC_GPS_ADR_STATE_UNKNOWN.
+ * However, it is expected that the data is only accurate when:
+ * 'accumulated delta range state' == LOC_GPS_ADR_STATE_VALID.
+ */
+ double accumulated_delta_range_m;
+
+ /**
+ * 1-Sigma uncertainty of the accumulated delta range in meters.
+ * This value must be populated if 'accumulated delta range state' != LOC_GPS_ADR_STATE_UNKNOWN.
+ */
+ double accumulated_delta_range_uncertainty_m;
+
+ /**
+ * Carrier frequency at which codes and messages are modulated, it can be L1 or L2.
+ * If the field is not set, the carrier frequency is assumed to be L1.
+ *
+ * If the data is available, 'flags' must contain
+ * LOC_GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY.
+ */
+ float carrier_frequency_hz;
+
+ /**
+ * The number of full carrier cycles between the satellite and the receiver.
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * Indications of possible cycle slips and resets in the accumulation of
+ * this value can be inferred from the accumulated_delta_range_state flags.
+ *
+ * If the data is available, 'flags' must contain
+ * LOC_GNSS_MEASUREMENT_HAS_CARRIER_CYCLES.
+ */
+ int64_t carrier_cycles;
+
+ /**
+ * The RF phase detected by the receiver, in the range [0.0, 1.0].
+ * This is usually the fractional part of the complete carrier phase measurement.
+ *
+ * The reference frequency is given by the field 'carrier_frequency_hz'.
+ * The value contains the 'carrier-phase uncertainty' in it.
+ *
+ * If the data is available, 'flags' must contain
+ * LOC_GNSS_MEASUREMENT_HAS_CARRIER_PHASE.
+ */
+ double carrier_phase;
+
+ /**
+ * 1-Sigma uncertainty of the carrier-phase.
+ * If the data is available, 'flags' must contain
+ * LOC_GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY.
+ */
+ double carrier_phase_uncertainty;
+
+ /**
+ * An enumeration that indicates the 'multipath' state of the event.
+ *
+ * The multipath Indicator is intended to report the presence of overlapping
+ * signals that manifest as distorted correlation peaks.
+ *
+ * - if there is a distorted correlation peak shape, report that multipath
+ * is LOC_GNSS_MULTIPATH_INDICATOR_PRESENT.
+ * - if there is not a distorted correlation peak shape, report
+ * LOC_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT
+ * - if signals are too weak to discern this information, report
+ * LOC_GNSS_MULTIPATH_INDICATOR_UNKNOWN
+ *
+ * Example: when doing the standardized overlapping Multipath Performance
+ * test (3GPP TS 34.171) the Multipath indicator should report
+ * LOC_GNSS_MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+ * contain multipath, and LOC_GNSS_MULTIPATH_INDICATOR_NOT_PRESENT for those
+ * signals that are tracked and do not contain multipath.
+ */
+ LocGnssMultipathIndicator multipath_indicator;
+
+ /**
+ * Signal-to-noise ratio at correlator output in dB.
+ * If the data is available, 'flags' must contain LOC_GNSS_MEASUREMENT_HAS_SNR.
+ * This is the power ratio of the "correlation peak height above the
+ * observed noise floor" to "the noise RMS".
+ */
+ double snr_db;
+} LocGnssMeasurement;
+
+/**
+ * Legacy struct to represents a reading of GPS measurements.
+ * Deprecated, to be removed in the next Android release.
+ * Use LocGnssData instead.
+ */
+typedef struct {
+ /** set to sizeof(LocGpsData) */
+ size_t size;
+ size_t measurement_count;
+ LocGpsMeasurement measurements[LOC_GPS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ LocGpsClock clock;
+} LocGpsData;
+
+/**
+ * Represents a reading of GNSS measurements. For devices where LocGnssSystemInfo's
+ * year_of_hw is set to 2016+, it is mandatory that these be provided, on
+ * request, when the GNSS receiver is searching/tracking signals.
+ *
+ * - Reporting of GPS constellation measurements is mandatory.
+ * - Reporting of all tracked constellations are encouraged.
+ */
+typedef struct {
+ /** set to sizeof(LocGnssData) */
+ size_t size;
+
+ /** Number of measurements. */
+ size_t measurement_count;
+
+ /** The array of measurements. */
+ LocGnssMeasurement measurements[LOC_GNSS_MAX_MEASUREMENT];
+
+ /** The GPS clock time reading. */
+ LocGnssClock clock;
+} LocGnssData;
+
+/**
+ * The legacy callback for to report measurements from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * loc_gnss_measurement_callback() instead.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*loc_gps_measurement_callback) (LocGpsData* data);
+
+/**
+ * The callback for to report measurements from the HAL.
+ *
+ * Parameters:
+ * data - A data structure containing the measurements.
+ */
+typedef void (*loc_gnss_measurement_callback) (LocGnssData* data);
+
+typedef struct {
+ /** set to sizeof(LocGpsMeasurementCallbacks) */
+ size_t size;
+ loc_gps_measurement_callback measurement_callback;
+ loc_gnss_measurement_callback loc_gnss_measurement_callback;
+} LocGpsMeasurementCallbacks;
+
+#define LOC_GPS_MEASUREMENT_OPERATION_SUCCESS 0
+#define LOC_GPS_MEASUREMENT_ERROR_ALREADY_INIT -100
+#define LOC_GPS_MEASUREMENT_ERROR_GENERIC -101
+
+/**
+ * Extended interface for GPS Measurements support.
+ */
+typedef struct {
+ /** Set to sizeof(LocGpsMeasurementInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates at its own phase.
+ *
+ * Status:
+ * LOC_GPS_MEASUREMENT_OPERATION_SUCCESS
+ * LOC_GPS_MEASUREMENT_ERROR_ALREADY_INIT - if a callback has already been registered without a
+ * corresponding call to 'close'
+ * LOC_GPS_MEASUREMENT_ERROR_GENERIC - if any other error occurred, it is expected that the HAL
+ * will not generate any updates upon returning this error code.
+ */
+ int (*init) (LocGpsMeasurementCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} LocGpsMeasurementInterface;
+
+#if 0
+/**
+ * Legacy struct to represents a GPS navigation message (or a fragment of it).
+ * Deprecated, to be removed in the next Android release.
+ * Use GnssNavigationMessage instead.
+ */
+typedef struct {
+ /** set to sizeof(GpsNavigationMessage) */
+ size_t size;
+ int8_t prn;
+ GpsNavigationMessageType type;
+ NavigationMessageStatus status;
+ int16_t message_id;
+ int16_t submessage_id;
+ size_t data_length;
+ uint8_t* data;
+} GpsNavigationMessage;
+
+/** Represents a GPS navigation message (or a fragment of it). */
+typedef struct {
+ /** set to sizeof(GnssNavigationMessage) */
+ size_t size;
+
+ /**
+ * Satellite vehicle ID number, as defined in LocGnssSvInfo::svid
+ * This is a mandatory value.
+ */
+ int16_t svid;
+
+ /**
+ * The type of message contained in the structure.
+ * This is a mandatory value.
+ */
+ GnssNavigationMessageType type;
+
+ /**
+ * The status of the received navigation message.
+ * No need to send any navigation message that contains words with parity error and cannot be
+ * corrected.
+ */
+ NavigationMessageStatus status;
+
+ /**
+ * Message identifier. It provides an index so the complete Navigation
+ * Message can be assembled.
+ *
+ * - For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+ * id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+ * does not contain a 'frame id' and this value can be set to -1.)
+ *
+ * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+ *
+ * - For BeiDou D1, this refers to the frame number in the range of 1-24
+ *
+ * - For Beidou D2, this refers to the frame number, in the range of 1-120
+ *
+ * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+ * number, in the range of 1-12
+ *
+ * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+ * number in the range of 1-24
+ */
+ int16_t message_id;
+
+ /**
+ * Sub-message identifier. If required by the message 'type', this value
+ * contains a sub-index within the current message (or frame) that is being
+ * transmitted.
+ *
+ * - For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+ * the subframe number of the navigation message, in the range of 1-5.
+ *
+ * - For Glonass L1 C/A, this refers to the String number, in the range from
+ * 1-15
+ *
+ * - For Galileo F/NAV, this refers to the page type in the range 1-6
+ *
+ * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+ */
+ int16_t submessage_id;
+
+ /**
+ * The length of the data (in bytes) contained in the current message.
+ * If this value is different from zero, 'data' must point to an array of the same size.
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
+ *
+ * This is a mandatory value.
+ */
+ size_t data_length;
+
+ /**
+ * The data of the reported GPS message. The bytes (or words) specified
+ * using big endian format (MSB first).
+ *
+ * - For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+ * words. Each word (30 bits) should be fit into the last 30 bits in a
+ * 4-byte word (skip B31 and B32), with MSB first, for a total of 40
+ * bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+ *
+ * - For Glonass L1 C/A, each string contains 85 data bits, including the
+ * checksum. These bits should be fit into 11 bytes, with MSB first (skip
+ * B86-B88), covering a time period of 2 seconds.
+ *
+ * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+ * excluded). Each word should be fit into 30-bytes, with MSB first (skip
+ * B239, B240), covering a time period of 10 seconds.
+ *
+ * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+ * a total of 2x114 = 228 bits, (sync & tail excluded) that should be fit
+ * into 29 bytes, with MSB first (skip B229-B232).
+ */
+ uint8_t* data;
+
+} GnssNavigationMessage;
+
+/**
+ * The legacy callback to report an available fragment of a GPS navigation
+ * messages from the HAL.
+ *
+ * This callback is deprecated, and will be removed in the next release. Use
+ * gnss_navigation_message_callback() instead.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gps_navigation_message_callback) (GpsNavigationMessage* message);
+
+/**
+ * The callback to report an available fragment of a GPS navigation messages from the HAL.
+ *
+ * Parameters:
+ * message - The GPS navigation submessage/subframe representation.
+ */
+typedef void (*gnss_navigation_message_callback) (GnssNavigationMessage* message);
+
+typedef struct {
+ /** set to sizeof(GpsNavigationMessageCallbacks) */
+ size_t size;
+ gps_navigation_message_callback navigation_message_callback;
+ gnss_navigation_message_callback gnss_navigation_message_callback;
+} GpsNavigationMessageCallbacks;
+
+#define GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS 0
+#define GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT -100
+#define GPS_NAVIGATION_MESSAGE_ERROR_GENERIC -101
+
+/**
+ * Extended interface for GPS navigation message reporting support.
+ */
+typedef struct {
+ /** Set to sizeof(GpsNavigationMessageInterface) */
+ size_t size;
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ * After a successful call to 'init' the HAL must begin to provide updates as they become
+ * available.
+ *
+ * Status:
+ * GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS
+ * GPS_NAVIGATION_MESSAGE_ERROR_ALREADY_INIT - if a callback has already been registered
+ * without a corresponding call to 'close'.
+ * GPS_NAVIGATION_MESSAGE_ERROR_GENERIC - if any other error occurred, it is expected that
+ * the HAL will not generate any updates upon returning this error code.
+ */
+ int (*init) (GpsNavigationMessageCallbacks* callbacks);
+
+ /**
+ * Stops updates from the HAL, and unregisters the callback routines.
+ * After a call to stop, the previously registered callbacks must be considered invalid by the
+ * HAL.
+ * If stop is invoked without a previous 'init', this function should perform no work.
+ */
+ void (*close) ();
+
+} GpsNavigationMessageInterface;
+#endif
+
+/**
+ * Interface for passing GNSS configuration contents from platform to HAL.
+ */
+typedef struct {
+ /** Set to sizeof(LocGnssConfigurationInterface) */
+ size_t size;
+
+ /**
+ * Deliver GNSS configuration contents to HAL.
+ * Parameters:
+ * config_data - a pointer to a char array which holds what usually is expected from
+ file(/vendor/etc/gps.conf), i.e., a sequence of UTF8 strings separated by '\n'.
+ * length - total number of UTF8 characters in configuraiton data.
+ *
+ * IMPORTANT:
+ * GPS HAL should expect this function can be called multiple times. And it may be
+ * called even when GpsLocationProvider is already constructed and enabled. GPS HAL
+ * should maintain the existing requests for various callback regardless the change
+ * in configuration data.
+ */
+ void (*configuration_update) (const char* config_data, int32_t length);
+} LocGnssConfigurationInterface;
+
+__END_DECLS
+
+#endif /* LOC_GPS_H */
+
diff --git a/gps/utils/loc_log.cpp b/gps/utils/loc_log.cpp
new file mode 100644
index 0000000..2110683
--- /dev/null
+++ b/gps/utils/loc_log.cpp
@@ -0,0 +1,282 @@
+/* Copyright (c) 2011-2012, 2015, 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include "log_util.h"
+#include "loc_log.h"
+#include "msg_q.h"
+#include <loc_pla.h>
+#include "LogBuffer.h"
+#include <unordered_map>
+#include <fstream>
+#include <algorithm>
+#include <string>
+#include <cctype>
+#define BUFFER_SIZE 120
+#define LOG_TAG_LEVEL_CONF_FILE_PATH "/data/vendor/location/gps.prop"
+
+// Logging Improvements
+const char *loc_logger_boolStr[]={"False","True"};
+const char VOID_RET[] = "None";
+const char FROM_AFW[] = "===>";
+const char TO_MODEM[] = "--->";
+const char FROM_MODEM[] = "<---";
+const char TO_AFW[] = "<===";
+const char EXIT_TAG[] = "Exiting";
+const char ENTRY_TAG[] = "Entering";
+const char EXIT_ERROR_TAG[] = "Exiting with error";
+
+int build_type_prop = BUILD_TYPE_PROP_NA;
+
+const string gEmptyStr = "";
+const string gUnknownStr = "UNKNOWN";
+/* Logging Mechanism */
+loc_logger_s_type loc_logger;
+
+/* tag base logging control map*/
+static std::unordered_map<std::string, uint8_t> tag_level_map;
+static bool tag_map_inited = false;
+
+/* returns the least signification bit that is set in the mask
+ Param
+ mask - bit mask.
+ clearTheBit - if true, mask gets modified upon return.
+ returns 0 if mask is 0.
+*/
+uint64_t loc_get_least_bit(uint64_t& mask, bool clearTheBit) {
+ uint64_t bit = 0;
+
+ if (mask > 0) {
+ uint64_t less1 = mask - 1;
+ bit = mask & ~(less1);
+ if (clearTheBit) {
+ mask &= less1;
+ }
+ }
+
+ return bit;
+}
+
+string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl) {
+ string out;
+ while (mask > 0) {
+ out += loc_get_name_from_tbl(tbl, loc_get_least_bit(mask));
+ if (mask > 0) {
+ out += " | ";
+ }
+ }
+ return out;
+}
+
+DECLARE_TBL(loc_msg_q_status) =
+{
+ NAME_VAL( eMSG_Q_SUCCESS ),
+ NAME_VAL( eMSG_Q_FAILURE_GENERAL ),
+ NAME_VAL( eMSG_Q_INVALID_PARAMETER ),
+ NAME_VAL( eMSG_Q_INVALID_HANDLE ),
+ NAME_VAL( eMSG_Q_UNAVAILABLE_RESOURCE ),
+ NAME_VAL( eMSG_Q_INSUFFICIENT_BUFFER )
+};
+
+/* Find msg_q status name */
+const char* loc_get_msg_q_status(int status)
+{
+ return loc_get_name_from_val(loc_msg_q_status_tbl, (int64_t) status);
+}
+
+//Target names
+DECLARE_TBL(target_name) =
+{
+ NAME_VAL(GNSS_NONE),
+ NAME_VAL(GNSS_MSM),
+ NAME_VAL(GNSS_GSS),
+ NAME_VAL(GNSS_MDM),
+ NAME_VAL(GNSS_AUTO),
+ NAME_VAL(GNSS_UNKNOWN)
+};
+
+/*===========================================================================
+
+FUNCTION loc_get_target_name
+
+DESCRIPTION
+ Returns pointer to a string that contains name of the target
+
+ XX:XX:XX.000\0
+
+RETURN VALUE
+ The target name string
+
+===========================================================================*/
+const char *loc_get_target_name(unsigned int target)
+{
+ int64_t index = 0;
+ static char ret[BUFFER_SIZE];
+
+ snprintf(ret, sizeof(ret), " %s with%s SSC",
+ loc_get_name_from_val(target_name_tbl, getTargetGnssType(target)),
+ ((target & HAS_SSC) == HAS_SSC) ? gEmptyStr.c_str() : "out");
+
+ return ret;
+}
+
+
+/*===========================================================================
+
+FUNCTION loc_get_time
+
+DESCRIPTION
+ Logs a callback event header.
+ The pointer time_string should point to a buffer of at least 13 bytes:
+
+ XX:XX:XX.000\0
+
+RETURN VALUE
+ The time string
+
+===========================================================================*/
+char *loc_get_time(char *time_string, size_t buf_size)
+{
+ struct timeval now; /* sec and usec */
+ struct tm now_tm; /* broken-down time */
+ char hms_string[80]; /* HH:MM:SS */
+
+ gettimeofday(&now, NULL);
+ localtime_r(&now.tv_sec, &now_tm);
+
+ strftime(hms_string, sizeof hms_string, "%H:%M:%S", &now_tm);
+ snprintf(time_string, buf_size, "%s.%03d", hms_string, (int) (now.tv_usec / 1000));
+
+ return time_string;
+}
+
+/*===========================================================================
+FUNCTION get_timestamp
+
+DESCRIPTION
+ Generates a timestamp using the current system time
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Char pointer to the parameter str
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+char * get_timestamp(char *str, unsigned long buf_size)
+{
+ struct timeval tv;
+ struct timezone tz;
+ int hh, mm, ss;
+ gettimeofday(&tv, &tz);
+ hh = tv.tv_sec/3600%24;
+ mm = (tv.tv_sec%3600)/60;
+ ss = tv.tv_sec%60;
+ snprintf(str, buf_size, "%02d:%02d:%02d.%06ld", hh, mm, ss, tv.tv_usec);
+ return str;
+}
+
+/*===========================================================================
+
+FUNCTION log_buffer_insert
+
+DESCRIPTION
+ Insert a log sentence with specific level to the log buffer.
+
+RETURN VALUE
+ N/A
+
+===========================================================================*/
+void log_buffer_insert(char *str, unsigned long buf_size, int level)
+{
+ timespec tv;
+ clock_gettime(CLOCK_BOOTTIME, &tv);
+ uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
+ string ss = str;
+ loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime);
+}
+
+void log_tag_level_map_init()
+{
+ if (tag_map_inited) {
+ return;
+ }
+
+ std::string filename = LOG_TAG_LEVEL_CONF_FILE_PATH;
+
+ std::ifstream s(filename);
+ if (!s.is_open()) {
+ ALOGE("cannot open file:%s", LOG_TAG_LEVEL_CONF_FILE_PATH);
+ } else {
+ std::string line;
+ while (std::getline(s, line)) {
+ line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
+ int pos = line.find('=');
+ if (pos <= 0 || pos >= (line.size() - 1)) {
+ ALOGE("wrong format in gps.prop");
+ continue;
+ }
+ std::string tag = line.substr(0, pos);
+ std::string level = line.substr(pos+1, 1);
+ if (!std::isdigit(*(level.begin()))) {
+ ALOGE("wrong format in gps.prop");
+ continue;
+ }
+ tag_level_map[tag] = (uint8_t)std::stoul(level);
+ }
+ }
+ tag_map_inited = true;
+}
+
+int get_tag_log_level(const char* tag)
+{
+ if (!tag_map_inited) {
+ return -1;
+ }
+
+ // in case LOG_TAG isn't defined in a source file, use the global log level
+ if (tag == NULL) {
+ return loc_logger.DEBUG_LEVEL;
+ }
+ int log_level;
+ auto search = tag_level_map.find(std::string(tag));
+ if (tag_level_map.end() != search) {
+ log_level = search->second;
+ } else {
+ log_level = loc_logger.DEBUG_LEVEL;
+ }
+ return log_level;
+}
diff --git a/gps/utils/loc_log.h b/gps/utils/loc_log.h
new file mode 100644
index 0000000..b750932
--- /dev/null
+++ b/gps/utils/loc_log.h
@@ -0,0 +1,122 @@
+/* Copyright (c) 2011-2012, 2015, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_LOG_H
+#define LOC_LOG_H
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unordered_map>
+#include <string>
+#include "loc_target.h"
+#include "loc_misc_utils.h"
+
+using std::string;
+using std::unordered_map;
+
+typedef unordered_map<int64_t, string> NameValTbl;
+
+#define NAME_VAL(x) {x, "" #x ""}
+#define DECLARE_TBL(T) static const NameValTbl T##_tbl
+
+extern const string gEmptyStr;
+extern const string gUnknownStr;
+
+#define CHECK_MASK(type, value, mask_var, mask) \
+ (((mask_var) & (mask)) ? (type) (value) : (type) (-1))
+
+#define LOC_TABLE_SIZE(table) (sizeof(table)/sizeof((table)[0]))
+
+#define FIELDVAL_DEC(field) \
+ loc_put_tag_val(#field, to_string(field))
+#define FIELDVAL_DEC_ARR(field) \
+ loc_put_tag_val(#field, \
+ loc_parenthesize(loc_prim_arr_to_string(field, \
+ sizeof(field)/sizeof(field[0]))))
+#define FIELDVAL_HEX(field) \
+ loc_put_tag_val(#field, to_string_hex(field))
+#define FIELDVAL_HEX_ARR(field) \
+ loc_put_tag_val(#field, \
+ loc_parenthesize(loc_prim_arr_to_string(field, \
+ sizeof(field)/sizeof(field[0]), \
+ false)))
+#define FIELDVAL_ENUM(field, tbl) \
+ loc_put_tag_val(#field, \
+ loc_get_name_from_tbl(tbl, field, gUnknownStr))
+#define FIELDVAL_MASK(field, tbl) \
+ loc_put_tag_val(#field, \
+ to_string_hex((uint64_t)field) + " " + \
+ loc_parenthesize(loc_get_bit_defs(field, tbl)))
+
+/* get from a table of strings with index */
+/* tbl - map of <int, string> entries
+ key - key to the matching entry
+ defalt - default pointer in case of incorrect parameters
+ */
+inline static const string& loc_get_name_from_tbl(const NameValTbl& tbl, int64_t key,
+ const string& defalt = gEmptyStr) {
+ auto item = tbl.find(key);
+ if (item != tbl.end()) {
+ return item->second;
+ } else {
+ return defalt;
+ }
+}
+
+/* puts to string formatted "TAG: VAL" with option ending string, default to newline */
+inline string loc_put_tag_val(const string& tag, const string& val, const string& eol = "\n") {
+ return tag + ": " + val + eol;
+}
+
+inline string loc_parenthesize(const string& str) {
+ return "(" + str + ")";
+}
+
+/* Get names from value */
+inline const char* loc_get_name_from_val(const NameValTbl& table, int64_t value) {
+ return loc_get_name_from_tbl(table, value, gUnknownStr).c_str();
+}
+
+inline const char* log_succ_fail_string(int is_succ) {
+ return is_succ? "successful" : "failed";
+}
+
+/* prints mask into a string with bit definitions from tbl */
+/* mask - bit mask, to be expanded into " BIT_NAMEx | BIT_NAMEy ... "
+ tbl - a table with defs for each bit, defined as <bit, name> entries
+ {{bit0, "BIT0_NAME"}, {bit1, "BIT1_NAME"}, .... {bitn, "BITn_NAME"} }
+ entries - number of strings in the table
+ */
+string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl);
+uint64_t loc_get_least_bit(uint64_t& mask, bool clearThebit = true);
+const char* loc_get_msg_q_status(int status);
+const char* loc_get_target_name(unsigned int target);
+char *loc_get_time(char *time_string, size_t buf_size);
+
+#endif /* LOC_LOG_H */
diff --git a/gps/utils/loc_misc_utils.cpp b/gps/utils/loc_misc_utils.cpp
new file mode 100644
index 0000000..fbcaef4
--- /dev/null
+++ b/gps/utils/loc_misc_utils.cpp
@@ -0,0 +1,351 @@
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_misc_utils"
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <dlfcn.h>
+#include <math.h>
+#include <log_util.h>
+#include <loc_misc_utils.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#ifndef MSEC_IN_ONE_SEC
+#define MSEC_IN_ONE_SEC 1000ULL
+#endif
+#define GET_MSEC_FROM_TS(ts) ((ts.tv_sec * MSEC_IN_ONE_SEC) + (ts.tv_nsec + 500000)/1000000)
+
+int loc_util_split_string(char *raw_string, char **split_strings_ptr,
+ int max_num_substrings, char delimiter)
+{
+ int raw_string_index=0;
+ int num_split_strings=0;
+ unsigned char end_string=0;
+ int raw_string_length=0;
+
+ if(!raw_string || !split_strings_ptr) {
+ LOC_LOGE("%s:%d]: NULL parameters", __func__, __LINE__);
+ num_split_strings = -1;
+ goto err;
+ }
+ LOC_LOGD("%s:%d]: raw string: %s\n", __func__, __LINE__, raw_string);
+ raw_string_length = strlen(raw_string) + 1;
+ split_strings_ptr[num_split_strings] = &raw_string[raw_string_index];
+ for(raw_string_index=0; raw_string_index < raw_string_length; raw_string_index++) {
+ if(raw_string[raw_string_index] == '\0')
+ end_string=1;
+ if((raw_string[raw_string_index] == delimiter) || end_string) {
+ raw_string[raw_string_index] = '\0';
+ if (num_split_strings < max_num_substrings) {
+ LOC_LOGD("%s:%d]: split string: %s\n",
+ __func__, __LINE__, split_strings_ptr[num_split_strings]);
+ }
+ num_split_strings++;
+ if(((raw_string_index + 1) < raw_string_length) &&
+ (num_split_strings < max_num_substrings)) {
+ split_strings_ptr[num_split_strings] = &raw_string[raw_string_index+1];
+ }
+ else {
+ break;
+ }
+ }
+ if(end_string)
+ break;
+ }
+err:
+ LOC_LOGD("%s:%d]: num_split_strings: %d\n", __func__, __LINE__, num_split_strings);
+ return num_split_strings;
+}
+
+void loc_util_trim_space(char *org_string)
+{
+ char *scan_ptr, *write_ptr;
+ char *first_nonspace = NULL, *last_nonspace = NULL;
+
+ if(org_string == NULL) {
+ LOC_LOGE("%s:%d]: NULL parameter", __func__, __LINE__);
+ goto err;
+ }
+
+ scan_ptr = write_ptr = org_string;
+
+ while (*scan_ptr) {
+ //Find the first non-space character
+ if ( !isspace(*scan_ptr) && first_nonspace == NULL) {
+ first_nonspace = scan_ptr;
+ }
+ //Once the first non-space character is found in the
+ //above check, keep shifting the characters to the left
+ //to replace the spaces
+ if (first_nonspace != NULL) {
+ *(write_ptr++) = *scan_ptr;
+ //Keep track of which was the last non-space character
+ //encountered
+ //last_nonspace will not be updated in the case where
+ //the string ends with spaces
+ if ( !isspace(*scan_ptr)) {
+ last_nonspace = write_ptr;
+ }
+ }
+ scan_ptr++;
+ }
+ //Add NULL terminator after the last non-space character
+ if (last_nonspace) { *last_nonspace = '\0'; }
+err:
+ return;
+}
+
+inline void logDlError(const char* failedCall) {
+ const char * err = dlerror();
+ LOC_LOGe("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err);
+}
+
+void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName)
+{
+ void* sym = nullptr;
+ if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) {
+ if (nullptr == libHandle) {
+ libHandle = dlopen(libName, RTLD_NOW);
+ if (nullptr == libHandle) {
+ logDlError("dlopen");
+ }
+ }
+ // NOT else, as libHandle gets assigned 5 line above
+ if (nullptr != libHandle) {
+ sym = dlsym(libHandle, symName);
+ if (nullptr == sym) {
+ logDlError("dlsym");
+ }
+ }
+ } else {
+ LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; "
+ "symName (%p) can not be null.", libHandle, libName, symName);
+ }
+
+ return sym;
+}
+
+uint64_t getQTimerTickCount()
+{
+ uint64_t qTimerCount = 0;
+#if __aarch64__
+ asm volatile("mrs %0, cntvct_el0" : "=r" (qTimerCount));
+#elif defined (__i386__) || defined (__x86_64__)
+ /* Qtimer not supported in x86 architecture */
+ qTimerCount = 0;
+#else
+ asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (qTimerCount));
+#endif
+
+ return qTimerCount;
+}
+
+uint64_t getQTimerDeltaNanos()
+{
+ char qtimer_val_string[100];
+ char *temp;
+ uint64_t local_qtimer = 0, remote_qtimer = 0;
+ int mdm_fd = -1, wlan_fd = -1, ret = 0;
+ uint64_t delta = 0;
+
+ memset(qtimer_val_string, '\0', sizeof(qtimer_val_string));
+
+ char devNode[] = "/sys/bus/mhi/devices/0306_00.01.00/time_us";
+ for (; devNode[27] < 3 && mdm_fd < 0; devNode[27]++) {
+ mdm_fd = ::open(devNode, O_RDONLY);
+ if (mdm_fd < 0) {
+ LOC_LOGe("MDM open file: %s error: %s", devNode, strerror(errno));
+ }
+ }
+ if (mdm_fd > 0) {
+ ret = read(mdm_fd, qtimer_val_string, sizeof(qtimer_val_string)-1);
+ ::close(mdm_fd);
+ if (ret < 0) {
+ LOC_LOGe("MDM read time_us file error: %s", strerror(errno));
+ } else {
+ temp = qtimer_val_string;
+ temp = strchr(temp, ':');
+ temp = temp + 2;
+ local_qtimer = atoll(temp);
+
+ temp = strchr(temp, ':');
+ temp = temp + 2;
+ remote_qtimer = atoll(temp);
+
+ if (local_qtimer >= remote_qtimer) {
+ delta = (local_qtimer - remote_qtimer) * 1000;
+ }
+ LOC_LOGv("qtimer values in microseconds: local:%" PRIi64 " remote:%" PRIi64 ""
+ " delta in nanoseconds:%" PRIi64 "",
+ local_qtimer, remote_qtimer, delta);
+ }
+ }
+ return delta;
+}
+
+uint64_t getQTimerFreq()
+{
+#if __aarch64__
+ uint64_t val = 0;
+ asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
+#elif defined (__i386__) || defined (__x86_64__)
+ /* Qtimer not supported in x86 architecture */
+ uint64_t val = 0;
+#else
+ uint32_t val = 0;
+ asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+#endif
+ return val;
+}
+
+uint64_t getBootTimeMilliSec()
+{
+ struct timespec curTs;
+ clock_gettime(CLOCK_BOOTTIME, &curTs);
+ return (uint64_t)GET_MSEC_FROM_TS(curTs);
+}
+
+// Used for convert position/velocity from GSNS antenna based to VRP based
+void Matrix_MxV(float a[3][3], float b[3], float c[3]) {
+ int i, j;
+
+ for (i=0; i<3; i++) {
+ c[i] = 0.0f;
+ for (j=0; j<3; j++)
+ c[i] += a[i][j] * b[j];
+ }
+}
+
+// Used for convert position/velocity from GNSS antenna based to VRP based
+void Matrix_Skew(float a[3], float c[3][3]) {
+ c[0][0] = 0.0f;
+ c[0][1] = -a[2];
+ c[0][2] = a[1];
+ c[1][0] = a[2];
+ c[1][1] = 0.0f;
+ c[1][2] = -a[0];
+ c[2][0] = -a[1];
+ c[2][1] = a[0];
+ c[2][2] = 0.0f;
+}
+
+// Used for convert position/velocity from GNSS antenna based to VRP based
+void Euler2Dcm(float euler[3], float dcm[3][3]) {
+ float cr = 0.0, sr = 0.0, cp = 0.0, sp = 0.0, ch = 0.0, sh = 0.0;
+
+ cr = cosf(euler[0]);
+ sr = sinf(euler[0]);
+ cp = cosf(euler[1]);
+ sp = sinf(euler[1]);
+ ch = cosf(euler[2]);
+ sh = sinf(euler[2]);
+
+ dcm[0][0] = cp * ch;
+ dcm[0][1] = (sp*sr*ch) - (cr*sh);
+ dcm[0][2] = (cr*sp*ch) + (sh*sr);
+
+ dcm[1][0] = cp * sh;
+ dcm[1][1] = (sr*sp*sh) + (cr*ch);
+ dcm[1][2] = (cr*sp*sh) - (sr*ch);
+
+ dcm[2][0] = -sp;
+ dcm[2][1] = sr * cp;
+ dcm[2][2] = cr * cp;
+}
+
+// Used for convert position from GSNS based to VRP based
+// The converted position will be stored in the llaInfo parameter.
+#define A6DOF_WGS_A (6378137.0f)
+#define A6DOF_WGS_B (6335439.0f)
+#define A6DOF_WGS_E2 (0.00669437999014f)
+void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
+ float leverArm[3]) {
+ LOC_LOGv("lla: %f, %f, %f, lever arm: %f %f %f, "
+ "rollpitchyaw: %f %f %f",
+ lla[0], lla[1], lla[2],
+ leverArm[0], leverArm[1], leverArm[2],
+ rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2]);
+
+ float cnb[3][3];
+ memset(cnb, 0, sizeof(cnb));
+ Euler2Dcm(rollPitchYaw, cnb);
+
+ float sl = sin(lla[0]);
+ float cl = cos(lla[0]);
+ float sf = 1.0f / (1.0f - A6DOF_WGS_E2 * sl* sl);
+ float sfr = sqrtf(sf);
+
+ float rn = A6DOF_WGS_B * sf * sfr + lla[2];
+ float re = A6DOF_WGS_A * sfr + lla[2];
+
+ float deltaNEU[3];
+
+ // gps_pos_lla = imu_pos_lla + Cbn*la_b .* [1/geo.Rn; 1/(geo.Re*geo.cL); -1];
+ Matrix_MxV(cnb, leverArm, deltaNEU);
+
+ // NED to lla conversion
+ lla[0] = lla[0] + deltaNEU[0] / rn;
+ lla[1] = lla[1] + deltaNEU[1] / (re * cl);
+ lla[2] = lla[2] + deltaNEU[2];
+}
+
+// Used for convert velocity from GSNS based to VRP based
+// The converted velocity will be stored in the enuVelocity parameter.
+void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
+ float rollPitchYawRate[3], float leverArm[3]) {
+
+ LOC_LOGv("enu velocity: %f, %f, %f, lever arm: %f %f %f, roll pitch yaw: %f %f %f,"
+ "rollpitchyawRate: %f %f %f",
+ enuVelocity[0], enuVelocity[1], enuVelocity[2],
+ leverArm[0], leverArm[1], leverArm[2],
+ rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2],
+ rollPitchYawRate[0], rollPitchYawRate[1], rollPitchYawRate[2]);
+
+ float cnb[3][3];
+ memset(cnb, 0, sizeof(cnb));
+ Euler2Dcm(rollPitchYaw, cnb);
+
+ float skewLA[3][3];
+ memset(skewLA, 0, sizeof(skewLA));
+ Matrix_Skew(leverArm, skewLA);
+
+ float tmp[3];
+ float deltaEnuVelocity[3];
+ memset(tmp, 0, sizeof(tmp));
+ memset(deltaEnuVelocity, 0, sizeof(deltaEnuVelocity));
+ Matrix_MxV(skewLA, rollPitchYawRate, tmp);
+ Matrix_MxV(cnb, tmp, deltaEnuVelocity);
+
+ enuVelocity[0] = enuVelocity[0] - deltaEnuVelocity[0];
+ enuVelocity[1] = enuVelocity[1] - deltaEnuVelocity[1];
+ enuVelocity[2] = enuVelocity[2] - deltaEnuVelocity[2];
+}
diff --git a/gps/utils/loc_misc_utils.h b/gps/utils/loc_misc_utils.h
new file mode 100644
index 0000000..2335e57
--- /dev/null
+++ b/gps/utils/loc_misc_utils.h
@@ -0,0 +1,321 @@
+/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef _LOC_MISC_UTILS_H_
+#define _LOC_MISC_UTILS_H_
+#include <stdint.h>
+#include <ios>
+#include <string>
+#include <sstream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stddef.h>
+#include <stdint.h>
+/*===========================================================================
+FUNCTION loc_split_string
+
+DESCRIPTION:
+ This function is used to split a delimiter separated string into
+ sub-strings. This function does not allocate new memory to store the split
+ strings. Instead, it places '\0' in places of delimiters and assings the
+ starting address of the substring within the raw string as the string address
+ The input raw_string no longer remains to be a collection of sub-strings
+ after this function is executed.
+ Please make a copy of the input string before calling this function if
+ necessary
+
+PARAMETERS:
+ char *raw_string: is the original string with delimiter separated substrings
+ char **split_strings_ptr: is the arraw of pointers which will hold the addresses
+ of individual substrings
+ int max_num_substrings: is the maximum number of substrings that are expected
+ by the caller. The array of pointers in the above parameter
+ is usually this long
+ char delimiter: is the delimiter that separates the substrings. Examples: ' ', ';'
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ int Number of split strings
+
+SIDE EFFECTS
+ The input raw_string no longer remains a delimiter separated single string.
+
+EXAMPLE
+ delimiter = ' ' //space
+ raw_string = "hello new user" //delimiter is space ' '
+ addresses = 0123456789abcd
+ split_strings_ptr[0] = &raw_string[0]; //split_strings_ptr[0] contains "hello"
+ split_strings_ptr[1] = &raw_string[6]; //split_strings_ptr[1] contains "new"
+ split_strings_ptr[2] = &raw_string[a]; //split_strings_ptr[2] contains "user"
+
+===========================================================================*/
+int loc_util_split_string(char *raw_string, char **split_strings_ptr, int max_num_substrings,
+ char delimiter);
+
+/*===========================================================================
+FUNCTION trim_space
+
+DESCRIPTION
+ Removes leading and trailing spaces of the string
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ None
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+void loc_util_trim_space(char *org_string);
+
+/*===========================================================================
+FUNCTION dlGetSymFromLib
+
+DESCRIPTION
+ Handy function to get a pointer to a symbol from a library.
+
+ If libHandle is not null, it will be used as the handle to the library. In
+ that case libName wll not be used;
+ libHandle is an in / out parameter.
+ If libHandle is null, libName will be used to dlopen.
+ Either libHandle or libName must not be nullptr.
+ symName must not be null.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ pointer to symName. Could be nullptr if
+ Parameters are incorrect; or
+ libName can not be opened; or
+ symName can not be found.
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName);
+
+/*===========================================================================
+FUNCTION getQTimerTickCount
+
+DESCRIPTION
+ This function is used to read the QTimer ticks count. This value is globally maintained and
+ must be the same across all processors on a target.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ uint64_t QTimer tick count
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+uint64_t getQTimerTickCount();
+
+/*===========================================================================
+FUNCTION getQTimerDeltaNanos
+
+DESCRIPTION
+This function is used to read the the difference in nanoseconds between
+Qtimer on AP side and Qtimer on MP side for dual-SoC architectures such as Kona
+
+DEPENDENCIES
+N/A
+
+RETURN VALUE
+uint64_t QTimer difference in nanoseconds
+
+SIDE EFFECTS
+N/A
+===========================================================================*/
+uint64_t getQTimerDeltaNanos();
+
+/*===========================================================================
+FUNCTION getQTimerFreq
+
+DESCRIPTION
+ This function is used to read the QTimer frequency in hz. This value is globally maintained and
+ must be the same across all processors on a target.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ uint64_t QTimer frequency
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+uint64_t getQTimerFreq();
+
+/*===========================================================================
+FUNCTION getBootTimeMilliSec
+
+DESCRIPTION
+ This function is used to get boot time in milliseconds.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ uint64_t boot time in milliseconds
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+uint64_t getBootTimeMilliSec();
+
+#ifdef __cplusplus
+}
+#endif
+
+using std::hex;
+using std::string;
+using std::stringstream;
+
+/*===========================================================================
+FUNCTION to_string_hex
+
+DESCRIPTION
+ This function works similar to std::to_string, but puts only in hex format.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ string, of input val in hex format
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+template <typename T>
+string to_string_hex(T val) {
+ stringstream ss;
+ if (val < 0) {
+ val = -val;
+ ss << "-";
+ }
+ ss << hex << "0x" << val;
+ return ss.str();
+}
+
+/*===========================================================================
+FUNCTION loc_prim_arr_to_string
+
+DESCRIPTION
+ This function puts out primitive array in DEC or EHX format.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ string, space separated string of values in the input array, either
+ in decimal or hex format, depending on the value of decIfTrue
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+template <typename T>
+static string loc_prim_arr_to_string(T* arr, uint32_t size, bool decIfTrue = true) {
+ stringstream ss;
+ for (uint32_t i = 0; i < size; i++) {
+ ss << (decIfTrue ? to_string(arr[i]) : to_string_hex(arr[i]));
+ if (i != size - 1) {
+ ss << " ";
+ }
+ }
+ return ss.str();
+}
+
+/*===========================================================================
+FUNCTION qTimerTicksToNanos
+
+DESCRIPTION
+ Transform from ticks to nanoseconds, clock is 19.2 MHz
+ so the formula would be qtimer(ns) = (ticks * 1000000000) / 19200000
+ or simplified qtimer(ns) = (ticks * 10000) / 192.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Qtimer value in nanoseconds
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+inline uint64_t qTimerTicksToNanos(double qTimer) {
+ return (uint64_t((qTimer * double(10000ull)) / (double)192ull));
+}
+
+/*===========================================================================
+FUNCTION loc_convert_lla_gnss_to_vrp
+
+DESCRIPTION
+ This function converts lat/long/altitude from GNSS antenna based
+ to vehicle reference point based.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ The converted lat/long/altitude will be stored in the parameter of llaInfo.
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
+ float leverArm[3]);
+
+/*===========================================================================
+FUNCTION loc_convert_velocity_gnss_to_vrp
+
+DESCRIPTION
+ This function converts east/north/up velocity from GNSS antenna based
+ to vehicle reference point based.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ The converted east/north/up velocity will be stored in the parameter of
+ enuVelocity.
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
+ float rollPitchYawRate[3], float leverArm[3]);
+
+#endif //_LOC_MISC_UTILS_H_
diff --git a/gps/utils/loc_nmea.cpp b/gps/utils/loc_nmea.cpp
new file mode 100644
index 0000000..6b5e60e
--- /dev/null
+++ b/gps/utils/loc_nmea.cpp
@@ -0,0 +1,2347 @@
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "LocSvc_nmea"
+#include <loc_nmea.h>
+#include <math.h>
+#include <log_util.h>
+#include <loc_pla.h>
+#include <loc_cfg.h>
+
+#define GLONASS_SV_ID_OFFSET 64
+#define SBAS_SV_ID_OFFSET (87)
+#define QZSS_SV_ID_OFFSET (192)
+#define BDS_SV_ID_OFFSET (200)
+#define GALILEO_SV_ID_OFFSET (300)
+#define NAVIC_SV_ID_OFFSET (400)
+#define MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION 64
+#define MAX_SATELLITES_IN_USE 12
+#define MSEC_IN_ONE_WEEK 604800000ULL
+#define UTC_GPS_OFFSET_MSECS 315964800000ULL
+#define MAX_TAG_BLOCK_GROUP_CODE (99999)
+
+// GNSS system id according to NMEA spec
+#define SYSTEM_ID_GPS 1
+#define SYSTEM_ID_GLONASS 2
+#define SYSTEM_ID_GALILEO 3
+#define SYSTEM_ID_BDS 4
+#define SYSTEM_ID_QZSS 5
+#define SYSTEM_ID_NAVIC 6
+
+//GNSS signal id according to NMEA spec
+#define SIGNAL_ID_ALL_SIGNALS 0
+#define SIGNAL_ID_GPS_L1CA 1
+#define SIGNAL_ID_GPS_L1P 2
+#define SIGNAL_ID_GPS_L1M 3
+#define SIGNAL_ID_GPS_L2P 4
+#define SIGNAL_ID_GPS_L2CM 5
+#define SIGNAL_ID_GPS_L2CL 6
+#define SIGNAL_ID_GPS_L5I 7
+#define SIGNAL_ID_GPS_L5Q 8
+
+
+#define SIGNAL_ID_GLO_G1CA 1
+#define SIGNAL_ID_GLO_G1P 2
+#define SIGNAL_ID_GLO_G2CA 3
+#define SIGNAL_ID_GLO_G2P 4
+
+
+#define SIGNAL_ID_GAL_E5A 1
+#define SIGNAL_ID_GAL_E5B 2
+#define SIGNAL_ID_GAL_E5AB 3
+#define SIGNAL_ID_GAL_E6A 4
+#define SIGNAL_ID_GAL_E6BC 5
+#define SIGNAL_ID_GAL_L1A 6
+#define SIGNAL_ID_GAL_L1BC 7
+
+#define SIGNAL_ID_BDS_B1I 1
+#define SIGNAL_ID_BDS_B1Q 2
+#define SIGNAL_ID_BDS_B1C 3
+#define SIGNAL_ID_BDS_B1A 4
+#define SIGNAL_ID_BDS_B2A 5
+#define SIGNAL_ID_BDS_B2B 6
+#define SIGNAL_ID_BDS_B2AB 7
+#define SIGNAL_ID_BDS_B3I 8
+#define SIGNAL_ID_BDS_B3Q 9
+#define SIGNAL_ID_BDS_B3A 0xA
+#define SIGNAL_ID_BDS_B2I 0xB
+#define SIGNAL_ID_BDS_B2Q 0xC
+
+#define SIGNAL_ID_QZSS_L1CA 1
+#define SIGNAL_ID_QZSS_L1CD 2
+#define SIGNAL_ID_QZSS_L1CP 3
+#define SIGNAL_ID_QZSS_LIS 4
+#define SIGNAL_ID_QZSS_L2CM 5
+#define SIGNAL_ID_QZSS_L2CL 6
+#define SIGNAL_ID_QZSS_L5I 7
+#define SIGNAL_ID_QZSS_L5Q 8
+#define SIGNAL_ID_QZSS_L6D 9
+#define SIGNAL_ID_QZSS_L6E 0xA
+
+#define SIGNAL_ID_NAVIC_L5SPS 1
+#define SIGNAL_ID_NAVIC_SSPS 2
+#define SIGNAL_ID_NAVIC_L5RS 3
+#define SIGNAL_ID_NAVIC_SRS 4
+#define SIGNAL_ID_NAVIC_L1SPS 5
+
+
+typedef struct loc_nmea_sv_meta_s
+{
+ char talker[3];
+ uint32_t svTypeMask;
+ uint64_t mask;
+ uint32_t svCount;
+ uint32_t totalSvUsedCount;
+ uint32_t svIdOffset;
+ uint32_t signalId;
+ uint32_t systemId;
+} loc_nmea_sv_meta;
+
+typedef struct loc_sv_cache_info_s
+{
+ uint64_t gps_used_mask;
+ uint64_t glo_used_mask;
+ uint64_t gal_used_mask;
+ uint64_t qzss_used_mask;
+ uint64_t bds_used_mask;
+ uint64_t navic_used_mask;
+ uint32_t gps_l1_count;
+ uint32_t gps_l2_count;
+ uint32_t gps_l5_count;
+ uint32_t glo_g1_count;
+ uint32_t glo_g2_count;
+ uint32_t gal_e1_count;
+ uint32_t gal_e5_count;
+ uint32_t gal_e5b_count;
+ uint32_t qzss_l1_count;
+ uint32_t qzss_l2_count;
+ uint32_t qzss_l5_count;
+ uint32_t bds_b1i_count;
+ uint32_t bds_b1c_count;
+ uint32_t bds_b2_count;
+ uint32_t navic_l5_count;
+ float hdop;
+ float pdop;
+ float vdop;
+} loc_sv_cache_info;
+
+/*===========================================================================
+FUNCTION convert_Lla_to_Ecef
+
+DESCRIPTION
+ Convert LLA to ECEF
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ NONE
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void convert_Lla_to_Ecef(const LocLla& plla, LocEcef& pecef)
+{
+ double r;
+
+ r = MAJA / sqrt(1.0 - ESQR * sin(plla.lat) * sin(plla.lat));
+ pecef.X = (r + plla.alt) * cos(plla.lat) * cos(plla.lon);
+ pecef.Y = (r + plla.alt) * cos(plla.lat) * sin(plla.lon);
+ pecef.Z = (r * OMES + plla.alt) * sin(plla.lat);
+}
+
+/*===========================================================================
+FUNCTION convert_WGS84_to_PZ90
+
+DESCRIPTION
+ Convert datum from WGS84 to PZ90
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ NONE
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void convert_WGS84_to_PZ90(const LocEcef& pWGS84, LocEcef& pPZ90)
+{
+ double deltaX = DatumConstFromWGS84[0];
+ double deltaY = DatumConstFromWGS84[1];
+ double deltaZ = DatumConstFromWGS84[2];
+ double deltaScale = DatumConstFromWGS84[3];
+ double rotX = DatumConstFromWGS84[4];
+ double rotY = DatumConstFromWGS84[5];
+ double rotZ = DatumConstFromWGS84[6];
+
+ pPZ90.X = deltaX + deltaScale * (pWGS84.X + rotZ * pWGS84.Y - rotY * pWGS84.Z);
+ pPZ90.Y = deltaY + deltaScale * (pWGS84.Y - rotZ * pWGS84.X + rotX * pWGS84.Z);
+ pPZ90.Z = deltaZ + deltaScale * (pWGS84.Z + rotY * pWGS84.X - rotX * pWGS84.Y);
+}
+
+/*===========================================================================
+FUNCTION convert_Ecef_to_Lla
+
+DESCRIPTION
+ Convert ECEF to LLA
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ NONE
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void convert_Ecef_to_Lla(const LocEcef& pecef, LocLla& plla)
+{
+ double p, r;
+ double EcefA = C_PZ90A;
+ double EcefB = C_PZ90B;
+ double Ecef1Mf;
+ double EcefE2;
+ double Mu;
+ double Smu;
+ double Cmu;
+ double Phi;
+ double Sphi;
+ double N;
+
+ p = sqrt(pecef.X * pecef.X + pecef.Y * pecef.Y);
+ r = sqrt(p * p + pecef.Z * pecef.Z);
+ if (r < 1.0) {
+ plla.lat = 1.0;
+ plla.lon = 1.0;
+ plla.alt = 1.0;
+ }
+ Ecef1Mf = 1.0 - (EcefA - EcefB) / EcefA;
+ EcefE2 = 1.0 - (EcefB * EcefB) / (EcefA * EcefA);
+ if (p > 1.0) {
+ Mu = atan2(pecef.Z * (Ecef1Mf + EcefE2 * EcefA / r), p);
+ } else {
+ if (pecef.Z > 0.0) {
+ Mu = M_PI / 2.0;
+ } else {
+ Mu = -M_PI / 2.0;
+ }
+ }
+ Smu = sin(Mu);
+ Cmu = cos(Mu);
+ Phi = atan2(pecef.Z * Ecef1Mf + EcefE2 * EcefA * Smu * Smu * Smu,
+ Ecef1Mf * (p - EcefE2 * EcefA * Cmu * Cmu * Cmu));
+ Sphi = sin(Phi);
+ N = EcefA / sqrt(1.0 - EcefE2 * Sphi * Sphi);
+ plla.alt = p * cos(Phi) + pecef.Z * Sphi - EcefA * EcefA/N;
+ plla.lat = Phi;
+ if ( p > 1.0) {
+ plla.lon = atan2(pecef.Y, pecef.X);
+ } else {
+ plla.lon = 0.0;
+ }
+}
+
+/*===========================================================================
+FUNCTION convert_signalType_to_signalId
+
+DESCRIPTION
+ convert signalType to signal ID
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ value of signal ID
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static uint32_t convert_signalType_to_signalId(GnssSignalTypeMask signalType)
+{
+ uint32_t signalId = SIGNAL_ID_ALL_SIGNALS;
+
+ switch (signalType) {
+ case GNSS_SIGNAL_GPS_L1CA:
+ case GNSS_SIGNAL_SBAS_L1:
+ signalId = SIGNAL_ID_GPS_L1CA;
+ break;
+ case GNSS_SIGNAL_GPS_L2:
+ signalId = SIGNAL_ID_GPS_L2CL;
+ break;
+ case GNSS_SIGNAL_GPS_L5:
+ signalId = SIGNAL_ID_GPS_L5Q;
+ break;
+ case GNSS_SIGNAL_GLONASS_G1:
+ signalId = SIGNAL_ID_GLO_G1CA;
+ break;
+ case GNSS_SIGNAL_GLONASS_G2:
+ signalId = SIGNAL_ID_GLO_G2CA;
+ break;
+ case GNSS_SIGNAL_GALILEO_E1:
+ signalId = SIGNAL_ID_GAL_L1BC;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5A:
+ signalId = SIGNAL_ID_GAL_E5A;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5B:
+ signalId = SIGNAL_ID_GAL_E5B;
+ break;
+ case GNSS_SIGNAL_QZSS_L1CA:
+ signalId = SIGNAL_ID_QZSS_L1CA;
+ break;
+ case GNSS_SIGNAL_QZSS_L2:
+ signalId = SIGNAL_ID_QZSS_L2CL;
+ break;
+ case GNSS_SIGNAL_QZSS_L5:
+ signalId = SIGNAL_ID_QZSS_L5Q;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B1I:
+ signalId = SIGNAL_ID_BDS_B1I;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B1C:
+ signalId = SIGNAL_ID_BDS_B1C;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2I:
+ signalId = SIGNAL_ID_BDS_B2I;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2AI:
+ case GNSS_SIGNAL_BEIDOU_B2AQ:
+ signalId = SIGNAL_ID_BDS_B2A;
+ break;
+ case GNSS_SIGNAL_NAVIC_L5:
+ signalId = SIGNAL_ID_NAVIC_L5SPS;
+ break;
+ default:
+ signalId = SIGNAL_ID_ALL_SIGNALS;
+ }
+
+ return signalId;
+
+}
+
+/*===========================================================================
+FUNCTION get_sv_count_from_mask
+
+DESCRIPTION
+ get the sv count from bit mask
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ value of sv count
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static uint32_t get_sv_count_from_mask(uint64_t svMask, int totalSvCount)
+{
+ int index = 0;
+ uint32_t svCount = 0;
+
+ if(totalSvCount > MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION) {
+ LOC_LOGE("total SV count in this constellation %d exceeded limit %d",
+ totalSvCount, MAX_SV_COUNT_SUPPORTED_IN_ONE_CONSTELLATION);
+ }
+ for(index = 0; index < totalSvCount; index++) {
+ if(svMask & 0x1)
+ svCount += 1;
+ svMask >>= 1;
+ }
+ return svCount;
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_sv_meta_init
+
+DESCRIPTION
+ Init loc_nmea_sv_meta passed in
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ Pointer to loc_nmea_sv_meta
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta,
+ loc_sv_cache_info& sv_cache_info,
+ GnssSvType svType,
+ GnssSignalTypeMask signalType,
+ bool needCombine)
+{
+ memset(&sv_meta, 0, sizeof(sv_meta));
+ sv_meta.svTypeMask = (1 << svType);
+
+ switch (svType)
+ {
+ case GNSS_SV_TYPE_GPS:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'P';
+ sv_meta.mask = sv_cache_info.gps_used_mask;
+ sv_meta.systemId = SYSTEM_ID_GPS;
+ sv_meta.svTypeMask |= (1 << GNSS_SV_TYPE_SBAS);
+ switch (signalType) {
+ case GNSS_SIGNAL_GPS_L1CA:
+ sv_meta.svCount = sv_cache_info.gps_l1_count;
+ break;
+ case GNSS_SIGNAL_GPS_L5:
+ sv_meta.svCount = sv_cache_info.gps_l5_count;
+ break;
+ case GNSS_SIGNAL_GPS_L2:
+ sv_meta.svCount = sv_cache_info.gps_l2_count;
+ break;
+ }
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'L';
+ sv_meta.mask = sv_cache_info.glo_used_mask;
+ // GLONASS SV ids are from 65-96
+ sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET;
+ sv_meta.systemId = SYSTEM_ID_GLONASS;
+ switch (signalType) {
+ case GNSS_SIGNAL_GLONASS_G1:
+ sv_meta.svCount = sv_cache_info.glo_g1_count;
+ break;
+ case GNSS_SIGNAL_GLONASS_G2:
+ sv_meta.svCount = sv_cache_info.glo_g2_count;
+ break;
+ }
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'A';
+ sv_meta.mask = sv_cache_info.gal_used_mask;
+ // GALILEO SV ids are from 301-336, So keep svIdOffset 300
+ sv_meta.svIdOffset = GALILEO_SV_ID_OFFSET;
+ sv_meta.systemId = SYSTEM_ID_GALILEO;
+ switch (signalType) {
+ case GNSS_SIGNAL_GALILEO_E1:
+ sv_meta.svCount = sv_cache_info.gal_e1_count;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5A:
+ sv_meta.svCount = sv_cache_info.gal_e5_count;
+ break;
+ case GNSS_SIGNAL_GALILEO_E5B:
+ sv_meta.svCount = sv_cache_info.gal_e5b_count;
+ break;
+ }
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'Q';
+ sv_meta.mask = sv_cache_info.qzss_used_mask;
+ // QZSS SV ids are from 193-199. So keep svIdOffset 192
+ sv_meta.svIdOffset = QZSS_SV_ID_OFFSET;
+ sv_meta.systemId = SYSTEM_ID_QZSS;
+ switch (signalType) {
+ case GNSS_SIGNAL_QZSS_L1CA:
+ sv_meta.svCount = sv_cache_info.qzss_l1_count;
+ break;
+ case GNSS_SIGNAL_QZSS_L2:
+ sv_meta.svCount = sv_cache_info.qzss_l2_count;
+ break;
+ case GNSS_SIGNAL_QZSS_L5:
+ sv_meta.svCount = sv_cache_info.qzss_l5_count;
+ break;
+ }
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'B';
+ sv_meta.mask = sv_cache_info.bds_used_mask;
+ // BDS SV ids are from 201-237. So keep svIdOffset 200
+ sv_meta.svIdOffset = BDS_SV_ID_OFFSET;
+ sv_meta.systemId = SYSTEM_ID_BDS;
+ switch (signalType) {
+ case GNSS_SIGNAL_BEIDOU_B1I:
+ sv_meta.svCount = sv_cache_info.bds_b1i_count;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B1C:
+ sv_meta.svCount = sv_cache_info.bds_b1c_count;
+ break;
+ case GNSS_SIGNAL_BEIDOU_B2AI:
+ sv_meta.svCount = sv_cache_info.bds_b2_count;
+ break;
+ }
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'I';
+ sv_meta.mask = sv_cache_info.navic_used_mask;
+ // NAVIC SV ids are from 401-414. So keep svIdOffset 400
+ sv_meta.svIdOffset = NAVIC_SV_ID_OFFSET;
+ sv_meta.systemId = SYSTEM_ID_NAVIC;
+ switch (signalType) {
+ case GNSS_SIGNAL_NAVIC_L5:
+ sv_meta.svCount = sv_cache_info.navic_l5_count;
+ break;
+ }
+ break;
+ default:
+ LOC_LOGE("NMEA Error unknow constellation type: %d", svType);
+ return NULL;
+ }
+ sv_meta.signalId = convert_signalType_to_signalId(signalType);
+ sv_meta.totalSvUsedCount =
+ get_sv_count_from_mask(sv_cache_info.gps_used_mask,
+ GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1) +
+ get_sv_count_from_mask(sv_cache_info.glo_used_mask,
+ GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1) +
+ get_sv_count_from_mask(sv_cache_info.gal_used_mask,
+ GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1) +
+ get_sv_count_from_mask(sv_cache_info.qzss_used_mask,
+ QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1) +
+ get_sv_count_from_mask(sv_cache_info.bds_used_mask,
+ BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1) +
+ get_sv_count_from_mask(sv_cache_info.navic_used_mask,
+ NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
+ if (needCombine &&
+ (sv_cache_info.gps_used_mask ? 1 : 0) +
+ (sv_cache_info.glo_used_mask ? 1 : 0) +
+ (sv_cache_info.gal_used_mask ? 1 : 0) +
+ (sv_cache_info.qzss_used_mask ? 1 : 0) +
+ (sv_cache_info.bds_used_mask ? 1 : 0) +
+ (sv_cache_info.navic_used_mask ? 1 : 0) > 1)
+ {
+ // If GPS, GLONASS, Galileo, QZSS, BDS etc. are combined
+ // to obtain the reported position solution,
+ // talker shall be set to GN, to indicate that
+ // the satellites are used in a combined solution
+ sv_meta.talker[0] = 'G';
+ sv_meta.talker[1] = 'N';
+ }
+ return &sv_meta;
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_put_checksum
+
+DESCRIPTION
+ Generate NMEA sentences generated based on position report
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ Total length of the nmea sentence
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static int loc_nmea_put_checksum(char *pNmea, int maxSize, bool isTagBlock)
+{
+ uint8_t checksum = 0;
+ int length = 0;
+ int checksumLength = 0;
+ if(NULL == pNmea)
+ return 0;
+
+ pNmea++; //skip the $ or / for Tag Block
+ while (*pNmea != '\0')
+ {
+ checksum ^= *pNmea++;
+ length++;
+ }
+
+ if (isTagBlock) {
+ // length now contains tag block sentence string length not including / sign.
+ checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\\", checksum);
+ } else {
+ // length now contains nmea sentence string length not including $ sign.
+ checksumLength = snprintf(pNmea, (maxSize-length-1), "*%02X\r\n", checksum);
+ }
+ // total length of nmea sentence is length of nmea sentence inc $ sign plus
+ // length of checksum (+1 is to cover the $ character in the length).
+ return (length + checksumLength + 1);
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_generate_GSA
+
+DESCRIPTION
+ Generate NMEA GSA sentences generated based on position report
+ Currently below sentences are generated:
+ - $GPGSA : GPS DOP and active SVs
+ - $GLGSA : GLONASS DOP and active SVs
+ - $GAGSA : GALILEO DOP and active SVs
+ - $GNGSA : GNSS DOP and active SVs
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ Number of SVs used
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtended,
+ char* sentence,
+ int bufSize,
+ loc_nmea_sv_meta* sv_meta_p,
+ std::vector<std::string> &nmeaArraystr,
+ bool isTagBlockGroupingEnabled)
+{
+ if (!sentence || bufSize <= 0 || !sv_meta_p)
+ {
+ LOC_LOGE("NMEA Error invalid arguments.");
+ return 0;
+ }
+
+ char* pMarker = sentence;
+ int lengthRemaining = bufSize;
+ int length = 0;
+ int lengthTagBlock = 0;
+
+ uint32_t svUsedCount = 0;
+ uint32_t svUsedList[64] = {0};
+ uint32_t sentenceCount = 0;
+ uint32_t sentenceNumber = 1;
+ size_t svNumber = 1;
+ static uint32_t code = 1;
+
+ char fixType = '\0';
+
+ const char* talker = sv_meta_p->talker;
+ uint32_t svIdOffset = sv_meta_p->svIdOffset;
+ uint64_t mask = sv_meta_p->mask;
+
+ if (!(sv_meta_p->svTypeMask & (1 << GNSS_SV_TYPE_GLONASS))) {
+ svIdOffset = 0;
+ }
+
+ for (uint8_t i = 1; mask > 0 && svUsedCount < 64; i++)
+ {
+ if (mask & 1)
+ svUsedList[svUsedCount++] = i + svIdOffset;
+ mask = mask >> 1;
+ }
+
+ if (svUsedCount == 0) {
+ return 0;
+ } else {
+ sentenceNumber = 1;
+ sentenceCount = svUsedCount / 12 + (svUsedCount % 12 != 0);
+ svNumber = 1;
+ }
+ while (sentenceNumber <= sentenceCount) {
+ pMarker = sentence;
+ lengthRemaining = bufSize;
+ if (svUsedCount > 12 && isTagBlockGroupingEnabled) {
+ lengthTagBlock = snprintf(pMarker, lengthRemaining, "\\g:%d-%d-%d", sentenceNumber,
+ sentenceCount, code);
+ if (MAX_TAG_BLOCK_GROUP_CODE == code) {
+ code = 1;
+ }
+ lengthTagBlock = loc_nmea_put_checksum(sentence, bufSize, true);
+ pMarker += lengthTagBlock;
+ lengthRemaining -= lengthTagBlock;
+ }
+ if (sv_meta_p->totalSvUsedCount == 0)
+ fixType = '1'; // no fix
+ else if (sv_meta_p->totalSvUsedCount <= 3)
+ fixType = '2'; // 2D fix
+ else
+ fixType = '3'; // 3D fix
+
+ // Start printing the sentence
+ // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v,s*cc
+ // a : Mode : A : Automatic, allowed to automatically switch 2D/3D
+ // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
+ // xx : 12 SV ID
+ // p.p : Position DOP (Dilution of Precision)
+ // h.h : Horizontal DOP
+ // v.v : Vertical DOP
+ // s : GNSS System Id
+ // cc : Checksum value
+ length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType);
+ if (length < 0 || length >= lengthRemaining) {
+ LOC_LOGE("NMEA Error in string formatting");
+ return 0;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ // Add 12 satellite IDs
+ for (uint8_t i = 0; i < 12; i++, svNumber++)
+ {
+ if (svNumber <= svUsedCount)
+ length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[svNumber - 1]);
+ else
+ length = snprintf(pMarker, lengthRemaining, ",");
+
+ if (length < 0 || length >= lengthRemaining) {
+ LOC_LOGE("NMEA Error in string formatting");
+ return 0;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+ }
+
+ // Add the position/horizontal/vertical DOP values
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f,",
+ locationExtended.pdop,
+ locationExtended.hdop,
+ locationExtended.vdop);
+ }
+ else
+ { // no dop
+ length = snprintf(pMarker, lengthRemaining, ",,,");
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ // system id
+ length = snprintf(pMarker, lengthRemaining, "%d", sv_meta_p->systemId);
+ pMarker += length;
+ lengthRemaining -= length;
+
+ /* Sentence is ready, add checksum and broadcast */
+ length = loc_nmea_put_checksum(sentence + lengthTagBlock, bufSize - lengthTagBlock, false);
+ nmeaArraystr.push_back(sentence);
+ sentenceNumber++;
+ if (!isTagBlockGroupingEnabled) {
+ break;
+ }
+ }
+ if (svUsedCount > 12 && isTagBlockGroupingEnabled) {
+ code++;
+ }
+ return svUsedCount;
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_generate_GSV
+
+DESCRIPTION
+ Generate NMEA GSV sentences generated based on sv report
+ Currently below sentences are generated:
+ - $GPGSV: GPS Satellites in View
+ - $GLGSV: GLONASS Satellites in View
+ - $GAGSV: GALILEO Satellites in View
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ NONE
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify,
+ char* sentence,
+ int bufSize,
+ loc_nmea_sv_meta* sv_meta_p,
+ std::vector<std::string> &nmeaArraystr)
+{
+ if (!sentence || bufSize <= 0)
+ {
+ LOC_LOGE("NMEA Error invalid argument.");
+ return;
+ }
+
+ char* pMarker = sentence;
+ int lengthRemaining = bufSize;
+ int length = 0;
+ int sentenceCount = 0;
+ int sentenceNumber = 1;
+ size_t svNumber = 1;
+
+ const char* talker = sv_meta_p->talker;
+ uint32_t svIdOffset = sv_meta_p->svIdOffset;
+ int svCount = sv_meta_p->svCount;
+ if (svCount <= 0)
+ {
+ LOC_LOGV("No SV in view for talker ID:%s, signal ID:%X", talker, sv_meta_p->signalId);
+ return;
+ }
+
+ if ((1 << GNSS_SV_TYPE_GLONASS) & sv_meta_p->svTypeMask) {
+ svIdOffset = 0;
+ }
+ svNumber = 1;
+ sentenceNumber = 1;
+ sentenceCount = svCount / 4 + (svCount % 4 != 0);
+
+ while (sentenceNumber <= sentenceCount)
+ {
+ pMarker = sentence;
+ lengthRemaining = bufSize;
+
+ length = snprintf(pMarker, lengthRemaining, "$%sGSV,%d,%d,%02d",
+ talker, sentenceCount, sentenceNumber, svCount);
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ for (int i=0; (svNumber <= svNotify.count) && (i < 4); svNumber++)
+ {
+ GnssSignalTypeMask signalType = svNotify.gnssSvs[svNumber-1].gnssSignalTypeMask;
+ if (0 == signalType) {
+ // If no signal type in report, it means default L1,G1,E1,B1I
+ switch (svNotify.gnssSvs[svNumber - 1].type)
+ {
+ case GNSS_SV_TYPE_GPS:
+ signalType = GNSS_SIGNAL_GPS_L1CA;
+ break;
+ case GNSS_SV_TYPE_GLONASS:
+ signalType = GNSS_SIGNAL_GLONASS_G1;
+ break;
+ case GNSS_SV_TYPE_GALILEO:
+ signalType = GNSS_SIGNAL_GALILEO_E1;
+ break;
+ case GNSS_SV_TYPE_QZSS:
+ signalType = GNSS_SIGNAL_QZSS_L1CA;
+ break;
+ case GNSS_SV_TYPE_BEIDOU:
+ signalType = GNSS_SIGNAL_BEIDOU_B1I;
+ break;
+ case GNSS_SV_TYPE_SBAS:
+ signalType = GNSS_SIGNAL_SBAS_L1;
+ break;
+ case GNSS_SV_TYPE_NAVIC:
+ signalType = GNSS_SIGNAL_NAVIC_L5;
+ break;
+ default:
+ LOC_LOGE("NMEA Error unknow constellation type: %d",
+ svNotify.gnssSvs[svNumber - 1].type);
+ continue;
+ }
+ }
+
+ if ((sv_meta_p->svTypeMask & (1 << svNotify.gnssSvs[svNumber - 1].type)) &&
+ sv_meta_p->signalId == convert_signalType_to_signalId(signalType))
+ {
+ if (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svNumber - 1].type) {
+ svIdOffset = SBAS_SV_ID_OFFSET;
+ }
+ if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type &&
+ GLO_SV_PRN_SLOT_UNKNOWN == svNotify.gnssSvs[svNumber - 1].svId) {
+ length = snprintf(pMarker, lengthRemaining, ",,%02d,%03d,",
+ (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int
+ (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int
+ } else {
+ length = snprintf(pMarker, lengthRemaining, ",%02d,%02d,%03d,",
+ svNotify.gnssSvs[svNumber - 1].svId - svIdOffset,
+ (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int
+ (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int
+ }
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (svNotify.gnssSvs[svNumber - 1].cN0Dbhz > 0)
+ {
+ length = snprintf(pMarker, lengthRemaining,"%02d",
+ (int)(0.5 + svNotify.gnssSvs[svNumber - 1].cN0Dbhz)); //float to int
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+ }
+
+ i++;
+ }
+
+ }
+
+ // append signalId
+ length = snprintf(pMarker, lengthRemaining,",%X",sv_meta_p->signalId);
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = loc_nmea_put_checksum(sentence, bufSize, false);
+ nmeaArraystr.push_back(sentence);
+ sentenceNumber++;
+
+ } //while
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_generate_DTM
+
+DESCRIPTION
+ Generate NMEA DTM sentences generated based on position report
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ NONE
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_nmea_generate_DTM(const LocLla &ref_lla,
+ const LocLla &local_lla,
+ char *talker,
+ char *sentence,
+ int bufSize)
+{
+ char* pMarker = sentence;
+ int lengthRemaining = bufSize;
+ int length = 0;
+ int datum_type;
+ char ref_datum[4] = {0};
+ char local_datum[4] = {0};
+ double lla_offset[3] = {0};
+ char latHem, longHem;
+ double latMins, longMins;
+
+
+
+ datum_type = loc_get_datum_type();
+ switch (datum_type) {
+ case LOC_GNSS_DATUM_WGS84:
+ ref_datum[0] = 'W';
+ ref_datum[1] = '8';
+ ref_datum[2] = '4';
+ local_datum[0] = 'P';
+ local_datum[1] = '9';
+ local_datum[2] = '0';
+ break;
+ case LOC_GNSS_DATUM_PZ90:
+ ref_datum[0] = 'P';
+ ref_datum[1] = '9';
+ ref_datum[2] = '0';
+ local_datum[0] = 'W';
+ local_datum[1] = '8';
+ local_datum[2] = '4';
+ break;
+ default:
+ break;
+ }
+ length = snprintf(pMarker , lengthRemaining , "$%sDTM,%s,," , talker, local_datum);
+ if (length < 0 || length >= lengthRemaining) {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ lla_offset[0] = local_lla.lat - ref_lla.lat;
+ lla_offset[1] = fmod(local_lla.lon - ref_lla.lon, 360.0);
+ if (lla_offset[1] < -180.0) {
+ lla_offset[1] += 360.0;
+ } else if ( lla_offset[1] > 180.0) {
+ lla_offset[1] -= 360.0;
+ }
+ lla_offset[2] = local_lla.alt - ref_lla.alt;
+ if (lla_offset[0] > 0.0) {
+ latHem = 'N';
+ } else {
+ latHem = 'S';
+ lla_offset[0] *= -1.0;
+ }
+ latMins = fmod(lla_offset[0] * 60.0, 60.0);
+ if (lla_offset[1] < 0.0) {
+ longHem = 'W';
+ lla_offset[1] *= -1.0;
+ }else {
+ longHem = 'E';
+ }
+ longMins = fmod(lla_offset[1] * 60.0, 60.0);
+ length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,%.3lf,",
+ (uint8_t)floor(lla_offset[0]), latMins, latHem,
+ (uint8_t)floor(lla_offset[1]), longMins, longHem, lla_offset[2]);
+ if (length < 0 || length >= lengthRemaining) {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+ length = snprintf(pMarker , lengthRemaining , "%s" , ref_datum);
+ if (length < 0 || length >= lengthRemaining) {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = loc_nmea_put_checksum(sentence, bufSize, false);
+}
+
+/*===========================================================================
+FUNCTION get_utctime_with_leapsecond_transition
+
+DESCRIPTION
+ This function returns true if the position report is generated during
+ leap second transition period. If not, then the utc timestamp returned
+ will be set to the timestamp in the position report. If it is,
+ then the utc timestamp returned will need to take into account
+ of the leap second transition so that proper calendar year/month/date
+ can be calculated from the returned utc timestamp.
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ true: position report is generated in leap second transition period.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static bool get_utctime_with_leapsecond_transition(
+ const UlpLocation &location,
+ const GpsLocationExtended &locationExtended,
+ const LocationSystemInfo &systemInfo,
+ LocGpsUtcTime &utcPosTimestamp)
+{
+ bool inTransition = false;
+
+ // position report is not generated during leap second transition,
+ // we can use the UTC timestamp from position report as is
+ utcPosTimestamp = location.gpsLocation.timestamp;
+
+ // Check whether we are in leap second transition.
+ // If so, per NMEA spec, we need to display the extra second in format of 23:59:60
+ // with year/month/date not getting advanced.
+ if ((locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GPS_TIME) &&
+ ((systemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) &&
+ (systemInfo.leapSecondSysInfo.leapSecondInfoMask &
+ LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT))) {
+
+ const LeapSecondChangeInfo &leapSecondChangeInfo =
+ systemInfo.leapSecondSysInfo.leapSecondChangeInfo;
+ const GnssSystemTimeStructType &gpsTimestampLsChange =
+ leapSecondChangeInfo.gpsTimestampLsChange;
+
+ uint64_t gpsTimeLsChange = gpsTimestampLsChange.systemWeek * MSEC_IN_ONE_WEEK +
+ gpsTimestampLsChange.systemMsec;
+ uint64_t gpsTimePosReport = locationExtended.gpsTime.gpsWeek * MSEC_IN_ONE_WEEK +
+ locationExtended.gpsTime.gpsTimeOfWeekMs;
+ // we are only dealing with positive leap second change, as negative
+ // leap second change has never occurred and should not occur in future
+ if (leapSecondChangeInfo.leapSecondsAfterChange >
+ leapSecondChangeInfo.leapSecondsBeforeChange) {
+ // leap second adjustment is always 1 second at a time. It can happen
+ // every quarter end and up to four times per year.
+ if ((gpsTimePosReport >= gpsTimeLsChange) &&
+ (gpsTimePosReport < (gpsTimeLsChange + 1000))) {
+ inTransition = true;
+ utcPosTimestamp = gpsTimeLsChange + UTC_GPS_OFFSET_MSECS -
+ leapSecondChangeInfo.leapSecondsBeforeChange * 1000;
+
+ // we substract 1000 milli-seconds from UTC timestmap in order to calculate the
+ // proper year, month and date during leap second transtion.
+ // Let us give an example, assuming leap second transition is scheduled on 2019,
+ // Dec 31st mid night. When leap second transition is happening,
+ // instead of outputting the time as 2020, Jan, 1st, 00 hour, 00 min, and 00 sec.
+ // The time need to be displayed as 2019, Dec, 31st, 23 hour, 59 min and 60 sec.
+ utcPosTimestamp -= 1000;
+ }
+ }
+ }
+ return inTransition;
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_get_fix_quality
+
+DESCRIPTION
+ This function obtains the fix quality for GGA sentence, mode indicator
+ for RMC and VTG sentence based on nav solution mask and tech mask in
+ the postion report.
+
+DEPENDENCIES
+ NONE
+
+Output parameter
+ ggaGpsQuality: gps quality field in GGA sentence
+ rmcModeIndicator: mode indicator field in RMC sentence
+ vtgModeIndicator: mode indicator field in VTG sentence
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static void loc_nmea_get_fix_quality(const UlpLocation & location,
+ const GpsLocationExtended & locationExtended,
+ bool custom_gga_fix_quality,
+ char ggaGpsQuality[3],
+ char & rmcModeIndicator,
+ char & vtgModeIndicator,
+ char gnsModeIndicator[7]) {
+
+ ggaGpsQuality[0] = '0'; // 0 means no fix
+ rmcModeIndicator = 'N'; // N means no fix
+ vtgModeIndicator = 'N'; // N means no fix
+ memset(gnsModeIndicator, 'N', 6); // N means no fix
+ gnsModeIndicator[6] = '\0';
+ do {
+ if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)){
+ break;
+ }
+ // NOTE: Order of the check is important
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) {
+ if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) {
+ ggaGpsQuality[0] = '2'; // 2 means DGPS fix
+ rmcModeIndicator = 'P'; // P means precise
+ vtgModeIndicator = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'P'; // P means precise
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'P'; // P means precise
+ break;
+ } else if (LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask){
+ ggaGpsQuality[0] = '4'; // 4 means RTK Fixed fix
+ rmcModeIndicator = 'R'; // use R (RTK fixed)
+ vtgModeIndicator = 'D'; // use D (differential) as
+ // no RTK fixed defined for VTG in NMEA 183 spec
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'R'; // R means RTK fixed
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'R'; // R means RTK fixed
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'R'; // R means RTK fixed
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'R'; // R means RTK fixed
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'R'; // R means RTK fixed
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'R'; // R means RTK fixed
+ break;
+ } else if (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask){
+ ggaGpsQuality[0] = '5'; // 5 means RTK float fix
+ rmcModeIndicator = 'F'; // F means RTK float fix
+ vtgModeIndicator = 'D'; // use D (differential) as
+ // no RTK float defined for VTG in NMEA 183 spec
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'F'; // F means RTK float fix
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'F'; // F means RTK float fix
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'F'; // F means RTK float fix
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'F'; // F means RTK float fix
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'F'; // F means RTK float fix
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'F'; // F means RTK float fix
+ break;
+ } else if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask){
+ ggaGpsQuality[0] = '2'; // 2 means DGPS fix
+ rmcModeIndicator = 'D'; // D means differential
+ vtgModeIndicator = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'D'; // D means differential
+ break;
+ } else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask){
+ ggaGpsQuality[0] = '2'; // 2 means DGPS fix
+ rmcModeIndicator = 'D'; // D means differential
+ vtgModeIndicator = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'D'; // D means differential
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'D'; // D means differential
+ break;
+ }
+ }
+ // NOTE: Order of the check is important
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) {
+ if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask){
+ ggaGpsQuality[0] = '1'; // 1 means GPS
+ rmcModeIndicator = 'A'; // A means autonomous
+ vtgModeIndicator = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[0] = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[1] = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[2] = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[3] = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[4] = 'A'; // A means autonomous
+ if (locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask ? 1 : 0)
+ gnsModeIndicator[5] = 'A'; // A means autonomous
+ break;
+ } else if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){
+ ggaGpsQuality[0] = '6'; // 6 means estimated (dead reckoning)
+ rmcModeIndicator = 'E'; // E means estimated (dead reckoning)
+ vtgModeIndicator = 'E'; // E means estimated (dead reckoning)
+ memset(gnsModeIndicator, 'E', 6); // E means estimated (dead reckoning)
+ break;
+ }
+ }
+ } while (0);
+
+ do {
+ // check for customized nmea enabled or not
+ // with customized GGA quality enabled
+ // PPP fix w/o sensor: 59, PPP fix w/ sensor: 69
+ // DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62
+ // RTK fixed fix w/o sensor: 4, w/ sensor: 64
+ // RTK float fix w/o sensor: 5, w/ sensor: 65
+ // SPE fix w/o sensor: 1, and w/ sensor: 61
+ // Sensor dead reckoning fix: 6
+ if (true == custom_gga_fix_quality) {
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) {
+ // PPP fix w/o sensor: fix quality will now be 59
+ // PPP fix w sensor: fix quality will now be 69
+ if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) {
+ if ((locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) &&
+ (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask)) {
+ ggaGpsQuality[0] = '6';
+ ggaGpsQuality[1] = '9';
+ } else {
+ ggaGpsQuality[0] = '5';
+ ggaGpsQuality[1] = '9';
+ }
+ break;
+ }
+ }
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) {
+ if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){
+ char ggaQuality_copy = ggaGpsQuality[0];
+ ggaGpsQuality[0] = '6'; // 6 sensor assisted
+ // RTK fixed fix w/ sensor: fix quality will now be 64
+ // RTK float fix w/ sensor: 65
+ // DGNSS and/or SBAS correction fix and w/ sensor: 62
+ // GPS fix without correction and w/ sensor: 61
+ if ((LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask)||
+ (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask)||
+ (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask)||
+ (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask)||
+ (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask)) {
+ ggaGpsQuality[1] = ggaQuality_copy;
+ break;
+ }
+ }
+ }
+ }
+ } while (0);
+
+ LOC_LOGv("gps quality: %s, rmc mode indicator: %c, vtg mode indicator: %c",
+ ggaGpsQuality, rmcModeIndicator, vtgModeIndicator);
+}
+
+/*===========================================================================
+FUNCTION loc_nmea_generate_pos
+
+DESCRIPTION
+ Generate NMEA sentences generated based on position report
+ Currently below sentences are generated within this function:
+ - $GPGSA : GPS DOP and active SVs
+ - $GLGSA : GLONASS DOP and active SVs
+ - $GAGSA : GALILEO DOP and active SVs
+ - $GNGSA : GNSS DOP and active SVs
+ - $--VTG : Track made good and ground speed
+ - $--RMC : Recommended minimum navigation information
+ - $--GGA : Time, position and fix related data
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_nmea_generate_pos(const UlpLocation &location,
+ const GpsLocationExtended &locationExtended,
+ const LocationSystemInfo &systemInfo,
+ unsigned char generate_nmea,
+ bool custom_gga_fix_quality,
+ std::vector<std::string> &nmeaArraystr,
+ int& indexOfGGA,
+ bool isTagBlockGroupingEnabled)
+{
+ ENTRY_LOG();
+
+ indexOfGGA = -1;
+ LocGpsUtcTime utcPosTimestamp = 0;
+ bool inLsTransition = false;
+
+ inLsTransition = get_utctime_with_leapsecond_transition
+ (location, locationExtended, systemInfo, utcPosTimestamp);
+
+ time_t utcTime(utcPosTimestamp/1000);
+ struct tm result;
+ tm * pTm = gmtime_r(&utcTime, &result);
+ if (NULL == pTm) {
+ LOC_LOGE("gmtime failed");
+ return;
+ }
+
+ char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ char sentence_DTM[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ char sentence_RMC[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ char sentence_GNS[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ char sentence_GGA[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ char* pMarker = sentence;
+ int lengthRemaining = sizeof(sentence);
+ int length = 0;
+ int utcYear = pTm->tm_year % 100; // 2 digit year
+ int utcMonth = pTm->tm_mon + 1; // tm_mon starts at zero
+ int utcDay = pTm->tm_mday;
+ int utcHours = pTm->tm_hour;
+ int utcMinutes = pTm->tm_min;
+ int utcSeconds = pTm->tm_sec;
+ int utcMSeconds = (location.gpsLocation.timestamp)%1000;
+ int datum_type = loc_get_datum_type();
+ LocEcef ecef_w84;
+ LocEcef ecef_p90;
+ LocLla lla_w84;
+ LocLla lla_p90;
+ LocLla ref_lla;
+ LocLla local_lla;
+
+ if (inLsTransition) {
+ // During leap second transition, we need to display the extra
+ // leap second of hour, minute, second as (23:59:60)
+ utcHours = 23;
+ utcMinutes = 59;
+ utcSeconds = 60;
+ // As UTC timestamp is freezing during leap second transition,
+ // retrieve milli-seconds portion from GPS timestamp.
+ utcMSeconds = locationExtended.gpsTime.gpsTimeOfWeekMs % 1000;
+ }
+
+ loc_sv_cache_info sv_cache_info = {};
+
+ if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
+ sv_cache_info.gps_used_mask =
+ locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
+ sv_cache_info.glo_used_mask =
+ locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
+ sv_cache_info.gal_used_mask =
+ locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
+ sv_cache_info.bds_used_mask =
+ locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
+ sv_cache_info.qzss_used_mask =
+ locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
+ sv_cache_info.navic_used_mask =
+ locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
+ }
+
+ if (generate_nmea) {
+ char talker[3] = {'G', 'P', '\0'};
+ uint32_t svUsedCount = 0;
+ uint32_t count = 0;
+ loc_nmea_sv_meta sv_meta;
+ // -------------------
+ // ---$GPGSA/$GNGSA---
+ // -------------------
+
+ count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
+ GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled);
+ if (count > 0)
+ {
+ svUsedCount += count;
+ talker[0] = sv_meta.talker[0];
+ talker[1] = sv_meta.talker[1];
+ }
+
+ // -------------------
+ // ---$GLGSA/$GNGSA---
+ // -------------------
+
+ count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS,
+ GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr, isTagBlockGroupingEnabled);
+ if (count > 0)
+ {
+ svUsedCount += count;
+ talker[0] = sv_meta.talker[0];
+ talker[1] = sv_meta.talker[1];
+ }
+
+ // -------------------
+ // ---$GAGSA/$GNGSA---
+ // -------------------
+
+ count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
+ GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr, isTagBlockGroupingEnabled);
+ if (count > 0)
+ {
+ svUsedCount += count;
+ talker[0] = sv_meta.talker[0];
+ talker[1] = sv_meta.talker[1];
+ }
+
+ // ----------------------------
+ // ---$GBGSA/$GNGSA (BEIDOU)---
+ // ----------------------------
+ count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
+ GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr, isTagBlockGroupingEnabled);
+ if (count > 0)
+ {
+ svUsedCount += count;
+ talker[0] = sv_meta.talker[0];
+ talker[1] = sv_meta.talker[1];
+ }
+
+ // --------------------------
+ // ---$GQGSA/$GNGSA (QZSS)---
+ // --------------------------
+
+ count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
+ GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr, isTagBlockGroupingEnabled);
+ if (count > 0)
+ {
+ svUsedCount += count;
+ talker[0] = sv_meta.talker[0];
+ talker[1] = sv_meta.talker[1];
+ }
+
+ // if svUsedCount is 0, it means we do not generate any GSA sentence yet.
+ // in this case, generate an empty GSA sentence
+ if (svUsedCount == 0) {
+ strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+ }
+
+ char ggaGpsQuality[3] = {'0', '\0', '\0'};
+ char rmcModeIndicator = 'N';
+ char vtgModeIndicator = 'N';
+ char gnsModeIndicator[7] = {'N', 'N', 'N', 'N', 'N', 'N', '\0'};
+ loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality,
+ ggaGpsQuality, rmcModeIndicator, vtgModeIndicator, gnsModeIndicator);
+
+ // -------------------
+ // ------$--VTG-------
+ // -------------------
+
+ pMarker = sentence;
+ lengthRemaining = sizeof(sentence);
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_BEARING)
+ {
+ float magTrack = location.gpsLocation.bearing;
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
+ {
+ magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation;
+ if (magTrack < 0.0)
+ magTrack += 360.0;
+ else if (magTrack > 360.0)
+ magTrack -= 360.0;
+ }
+
+ length = snprintf(pMarker, lengthRemaining, "$%sVTG,%.1lf,T,%.1lf,M,", talker, location.gpsLocation.bearing, magTrack);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, "$%sVTG,,T,,M,", talker);
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_SPEED)
+ {
+ float speedKnots = location.gpsLocation.speed * (3600.0/1852.0);
+ float speedKmPerHour = location.gpsLocation.speed * 3.6;
+
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,N,%.1lf,K,", speedKnots, speedKmPerHour);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",N,,K,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = snprintf(pMarker, lengthRemaining, "%c", vtgModeIndicator);
+
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ memset(&ecef_w84, 0, sizeof(ecef_w84));
+ memset(&ecef_p90, 0, sizeof(ecef_p90));
+ memset(&lla_w84, 0, sizeof(lla_w84));
+ memset(&lla_p90, 0, sizeof(lla_p90));
+ memset(&ref_lla, 0, sizeof(ref_lla));
+ memset(&local_lla, 0, sizeof(local_lla));
+ lla_w84.lat = location.gpsLocation.latitude / 180.0 * M_PI;
+ lla_w84.lon = location.gpsLocation.longitude / 180.0 * M_PI;
+ lla_w84.alt = location.gpsLocation.altitude;
+
+ convert_Lla_to_Ecef(lla_w84, ecef_w84);
+ convert_WGS84_to_PZ90(ecef_w84, ecef_p90);
+ convert_Ecef_to_Lla(ecef_p90, lla_p90);
+
+ switch (datum_type) {
+ case LOC_GNSS_DATUM_WGS84:
+ ref_lla.lat = location.gpsLocation.latitude;
+ ref_lla.lon = location.gpsLocation.longitude;
+ ref_lla.alt = location.gpsLocation.altitude;
+ local_lla.lat = lla_p90.lat / M_PI * 180.0;
+ local_lla.lon = lla_p90.lon / M_PI * 180.0;
+ local_lla.alt = lla_p90.alt;
+ break;
+ case LOC_GNSS_DATUM_PZ90:
+ ref_lla.lat = lla_p90.lat / M_PI * 180.0;
+ ref_lla.lon = lla_p90.lon / M_PI * 180.0;
+ ref_lla.alt = lla_p90.alt;
+ local_lla.lat = location.gpsLocation.latitude;
+ local_lla.lon = location.gpsLocation.longitude;
+ local_lla.alt = location.gpsLocation.altitude;
+ break;
+ default:
+ break;
+ }
+
+ // -------------------
+ // ------$--DTM-------
+ // -------------------
+ loc_nmea_generate_DTM(ref_lla, local_lla, talker, sentence_DTM, sizeof(sentence_DTM));
+
+ // -------------------
+ // ------$--RMC-------
+ // -------------------
+
+ pMarker = sentence_RMC;
+ lengthRemaining = sizeof(sentence_RMC);
+
+ bool validFix = ((0 != sv_cache_info.gps_used_mask) ||
+ (0 != sv_cache_info.glo_used_mask) ||
+ (0 != sv_cache_info.gal_used_mask) ||
+ (0 != sv_cache_info.qzss_used_mask) ||
+ (0 != sv_cache_info.bds_used_mask));
+
+ if (validFix) {
+ length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A,",
+ talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
+ } else {
+ length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,V,",
+ talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)
+ {
+ double latitude = ref_lla.lat;
+ double longitude = ref_lla.lon;
+ char latHemisphere;
+ char lonHemisphere;
+ double latMinutes;
+ double lonMinutes;
+
+ if (latitude > 0)
+ {
+ latHemisphere = 'N';
+ }
+ else
+ {
+ latHemisphere = 'S';
+ latitude *= -1.0;
+ }
+
+ if (longitude < 0)
+ {
+ lonHemisphere = 'W';
+ longitude *= -1.0;
+ }
+ else
+ {
+ lonHemisphere = 'E';
+ }
+
+ latMinutes = fmod(latitude * 60.0 , 60.0);
+ lonMinutes = fmod(longitude * 60.0 , 60.0);
+
+ length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,",
+ (uint8_t)floor(latitude), latMinutes, latHemisphere,
+ (uint8_t)floor(longitude),lonMinutes, lonHemisphere);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining,",,,,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_SPEED)
+ {
+ float speedKnots = location.gpsLocation.speed * (3600.0/1852.0);
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,", speedKnots);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_BEARING)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,", location.gpsLocation.bearing);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = snprintf(pMarker, lengthRemaining, "%2.2d%2.2d%2.2d,",
+ utcDay, utcMonth, utcYear);
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
+ {
+ float magneticVariation = locationExtended.magneticDeviation;
+ char direction;
+ if (magneticVariation < 0.0)
+ {
+ direction = 'W';
+ magneticVariation *= -1.0;
+ }
+ else
+ {
+ direction = 'E';
+ }
+
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,%c,",
+ magneticVariation, direction);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = snprintf(pMarker, lengthRemaining, "%c", rmcModeIndicator);
+ pMarker += length;
+ lengthRemaining -= length;
+
+ // hardcode Navigation Status field to 'V'
+ length = snprintf(pMarker, lengthRemaining, ",%c", 'V');
+
+ length = loc_nmea_put_checksum(sentence_RMC, sizeof(sentence_RMC), false);
+
+ // -------------------
+ // ------$--GNS-------
+ // -------------------
+
+ pMarker = sentence_GNS;
+ lengthRemaining = sizeof(sentence_GNS);
+
+ length = snprintf(pMarker, lengthRemaining, "$%sGNS,%02d%02d%02d.%02d," ,
+ talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)
+ {
+ double latitude = ref_lla.lat;
+ double longitude = ref_lla.lon;
+ char latHemisphere;
+ char lonHemisphere;
+ double latMinutes;
+ double lonMinutes;
+
+ if (latitude > 0)
+ {
+ latHemisphere = 'N';
+ }
+ else
+ {
+ latHemisphere = 'S';
+ latitude *= -1.0;
+ }
+
+ if (longitude < 0)
+ {
+ lonHemisphere = 'W';
+ longitude *= -1.0;
+ }
+ else
+ {
+ lonHemisphere = 'E';
+ }
+
+ latMinutes = fmod(latitude * 60.0 , 60.0);
+ lonMinutes = fmod(longitude * 60.0 , 60.0);
+
+ length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,",
+ (uint8_t)floor(latitude), latMinutes, latHemisphere,
+ (uint8_t)floor(longitude),lonMinutes, lonHemisphere);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining,",,,,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = snprintf(pMarker, lengthRemaining, "%s,", gnsModeIndicator);
+
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) {
+ length = snprintf(pMarker, lengthRemaining, "%02d,%.1f,",
+ svUsedCount, locationExtended.hdop);
+ }
+ else { // no hdop
+ length = snprintf(pMarker, lengthRemaining, "%02d,,",
+ svUsedCount);
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,",
+ locationExtended.altitudeMeanSeaLevel);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining,",");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
+ (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL))
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,",
+ ref_lla.alt - locationExtended.altitudeMeanSeaLevel);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",");
+ }
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1f,",
+ (float)locationExtended.dgnssDataAgeMsec / 1000);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",");
+ }
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%04d",
+ locationExtended.dgnssRefStationId);
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+ }
+
+ // hardcode Navigation Status field to 'V'
+ length = snprintf(pMarker, lengthRemaining, ",%c", 'V');
+ pMarker += length;
+ lengthRemaining -= length;
+
+ length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS), false);
+
+ // -------------------
+ // ------$--GGA-------
+ // -------------------
+
+ pMarker = sentence_GGA;
+ lengthRemaining = sizeof(sentence_GGA);
+
+ length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," ,
+ talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)
+ {
+ double latitude = ref_lla.lat;
+ double longitude = ref_lla.lon;
+ char latHemisphere;
+ char lonHemisphere;
+ double latMinutes;
+ double lonMinutes;
+
+ if (latitude > 0)
+ {
+ latHemisphere = 'N';
+ }
+ else
+ {
+ latHemisphere = 'S';
+ latitude *= -1.0;
+ }
+
+ if (longitude < 0)
+ {
+ lonHemisphere = 'W';
+ longitude *= -1.0;
+ }
+ else
+ {
+ lonHemisphere = 'E';
+ }
+
+ latMinutes = fmod(latitude * 60.0 , 60.0);
+ lonMinutes = fmod(longitude * 60.0 , 60.0);
+
+ length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,",
+ (uint8_t)floor(latitude), latMinutes, latHemisphere,
+ (uint8_t)floor(longitude),lonMinutes, lonHemisphere);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining,",,,,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ // Number of satellites in use, 00-12
+ if (svUsedCount > MAX_SATELLITES_IN_USE)
+ svUsedCount = MAX_SATELLITES_IN_USE;
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%s,%02d,%.1f,",
+ ggaGpsQuality, svUsedCount, locationExtended.hdop);
+ }
+ else
+ { // no hdop
+ length = snprintf(pMarker, lengthRemaining, "%s,%02d,,",
+ ggaGpsQuality, svUsedCount);
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,M,",
+ locationExtended.altitudeMeanSeaLevel);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining,",,");
+ }
+
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if ((location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
+ (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL))
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1lf,M,",
+ ref_lla.alt - locationExtended.altitudeMeanSeaLevel);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",,");
+ }
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_DATA_AGE)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%.1f,",
+ (float)locationExtended.dgnssDataAgeMsec / 1000);
+ }
+ else
+ {
+ length = snprintf(pMarker, lengthRemaining, ",");
+ }
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+
+ if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DGNSS_REF_STATION_ID)
+ {
+ length = snprintf(pMarker, lengthRemaining, "%04d",
+ locationExtended.dgnssRefStationId);
+ if (length < 0 || length >= lengthRemaining)
+ {
+ LOC_LOGE("NMEA Error in string formatting");
+ return;
+ }
+ pMarker += length;
+ lengthRemaining -= length;
+ }
+
+ length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA), false);
+
+ // ------$--DTM-------
+ nmeaArraystr.push_back(sentence_DTM);
+ // ------$--RMC-------
+ nmeaArraystr.push_back(sentence_RMC);
+ if(LOC_GNSS_DATUM_PZ90 == datum_type) {
+ // ------$--DTM-------
+ nmeaArraystr.push_back(sentence_DTM);
+ }
+ // ------$--GNS-------
+ nmeaArraystr.push_back(sentence_GNS);
+ if(LOC_GNSS_DATUM_PZ90 == datum_type) {
+ // ------$--DTM-------
+ nmeaArraystr.push_back(sentence_DTM);
+ }
+ // ------$--GGA-------
+ nmeaArraystr.push_back(sentence_GGA);
+ indexOfGGA = static_cast<int>(nmeaArraystr.size() - 1);
+ }
+ //Send blank NMEA reports for non-final fixes
+ else {
+ strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+
+ strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence));
+ length = loc_nmea_put_checksum(sentence, sizeof(sentence), false);
+ nmeaArraystr.push_back(sentence);
+ }
+
+ EXIT_LOG(%d, 0);
+}
+
+
+
+/*===========================================================================
+FUNCTION loc_nmea_generate_sv
+
+DESCRIPTION
+ Generate NMEA sentences generated based on sv report
+
+DEPENDENCIES
+ NONE
+
+RETURN VALUE
+ 0
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+void loc_nmea_generate_sv(const GnssSvNotification &svNotify,
+ std::vector<std::string> &nmeaArraystr)
+{
+ ENTRY_LOG();
+
+ char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
+ loc_sv_cache_info sv_cache_info = {};
+
+ //Count GPS SVs for saparating GPS from GLONASS and throw others
+ for (uint32_t svOffset = 0; svOffset < svNotify.count; svOffset++) {
+ if ((GNSS_SV_TYPE_GPS == svNotify.gnssSvs[svOffset].type) ||
+ (GNSS_SV_TYPE_SBAS == svNotify.gnssSvs[svOffset].type))
+ {
+ if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.gps_l5_count++;
+ } else if (GNSS_SIGNAL_GPS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.gps_l2_count++;
+ } else {
+ // GNSS_SIGNAL_GPS_L1CA, GNSS_SIGNAL_SBAS_L1 or default
+ // If no signal type in report, it means default L1
+ sv_cache_info.gps_l1_count++;
+ }
+ }
+ else if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svOffset].type)
+ {
+ if (GNSS_SIGNAL_GLONASS_G2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask){
+ sv_cache_info.glo_g2_count++;
+ } else {
+ // GNSS_SIGNAL_GLONASS_G1 or default
+ // If no signal type in report, it means default G1
+ sv_cache_info.glo_g1_count++;
+ }
+ }
+ else if (GNSS_SV_TYPE_GALILEO == svNotify.gnssSvs[svOffset].type)
+ {
+ if(GNSS_SIGNAL_GALILEO_E5A == svNotify.gnssSvs[svOffset].gnssSignalTypeMask){
+ sv_cache_info.gal_e5_count++;
+ } else if (GNSS_SIGNAL_GALILEO_E5B == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.gal_e5b_count++;
+ } else {
+ // GNSS_SIGNAL_GALILEO_E1 or default
+ // If no signal type in report, it means default E1
+ sv_cache_info.gal_e1_count++;
+ }
+ }
+ else if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svOffset].type)
+ {
+ if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.qzss_l5_count++;
+ } else if (GNSS_SIGNAL_QZSS_L2 == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.qzss_l2_count++;
+ } else {
+ // GNSS_SIGNAL_QZSS_L1CA or default
+ // If no signal type in report, it means default L1
+ sv_cache_info.qzss_l1_count++;
+ }
+ }
+ else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svOffset].type)
+ {
+ // cache the used in fix mask, as it will be needed to send $PQGSA
+ // during the position report
+ if (GNSS_SV_OPTIONS_USED_IN_FIX_BIT ==
+ (svNotify.gnssSvs[svOffset].gnssSvOptionsMask &
+ GNSS_SV_OPTIONS_USED_IN_FIX_BIT))
+ {
+ setSvMask(sv_cache_info.bds_used_mask, svNotify.gnssSvs[svOffset].svId);
+ }
+ if ((GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) ||
+ (GNSS_SIGNAL_BEIDOU_B2AQ == svNotify.gnssSvs[svOffset].gnssSignalTypeMask)) {
+ sv_cache_info.bds_b2_count++;
+ } else if (GNSS_SIGNAL_BEIDOU_B1C == svNotify.gnssSvs[svOffset].gnssSignalTypeMask) {
+ sv_cache_info.bds_b1c_count++;
+ } else {
+ // GNSS_SIGNAL_BEIDOU_B1I or default
+ // If no signal type in report, it means default B1I
+ sv_cache_info.bds_b1i_count++;
+ }
+ }
+ else if (GNSS_SV_TYPE_NAVIC == svNotify.gnssSvs[svOffset].type)
+ {
+ // GNSS_SIGNAL_NAVIC_L5 is the only signal type for NAVIC
+ sv_cache_info.navic_l5_count++;
+ }
+ }
+
+ loc_nmea_sv_meta sv_meta;
+ // ---------------------
+ // ------$GPGSV:L1CA----
+ // ---------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
+ GNSS_SIGNAL_GPS_L1CA, false), nmeaArraystr);
+
+ // ---------------------
+ // ------$GPGSV:L5------
+ // ---------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
+ GNSS_SIGNAL_GPS_L5, false), nmeaArraystr);
+
+ // ---------------------
+ // ------$GPGSV:L2------
+ // ---------------------
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS,
+ GNSS_SIGNAL_GPS_L2, false), nmeaArraystr);
+
+ // ---------------------
+ // ------$GLGSV:G1------
+ // ---------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS,
+ GNSS_SIGNAL_GLONASS_G1, false), nmeaArraystr);
+
+ // ---------------------
+ // ------$GLGSV:G2------
+ // ---------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS,
+ GNSS_SIGNAL_GLONASS_G2, false), nmeaArraystr);
+
+ // ---------------------
+ // ------$GAGSV:E1------
+ // ---------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
+ GNSS_SIGNAL_GALILEO_E1, false), nmeaArraystr);
+
+ // -------------------------
+ // ------$GAGSV:E5A---------
+ // -------------------------
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
+ GNSS_SIGNAL_GALILEO_E5A, false), nmeaArraystr);
+
+ // -------------------------
+ // ------$GAGSV:E5B---------
+ // -------------------------
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO,
+ GNSS_SIGNAL_GALILEO_E5B, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GQGSV (QZSS):L1CA-----
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
+ GNSS_SIGNAL_QZSS_L1CA, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GQGSV (QZSS):L5-------
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
+ GNSS_SIGNAL_QZSS_L5, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GQGSV (QZSS):L2-------
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS,
+ GNSS_SIGNAL_QZSS_L2, false), nmeaArraystr);
+
+
+ // -----------------------------
+ // ------$GBGSV (BEIDOU:B1I)----
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
+ GNSS_SIGNAL_BEIDOU_B1I, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GBGSV (BEIDOU:B1C)----
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
+ GNSS_SIGNAL_BEIDOU_B1C, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GBGSV (BEIDOU:B2AI)---
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU,
+ GNSS_SIGNAL_BEIDOU_B2AI, false), nmeaArraystr);
+
+ // -----------------------------
+ // ------$GIGSV (NAVIC:L5)------
+ // -----------------------------
+
+ loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence),
+ loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_NAVIC,
+ GNSS_SIGNAL_NAVIC_L5,false), nmeaArraystr);
+
+ EXIT_LOG(%d, 0);
+}
diff --git a/gps/utils/loc_nmea.h b/gps/utils/loc_nmea.h
new file mode 100644
index 0000000..2d98f42
--- /dev/null
+++ b/gps/utils/loc_nmea.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2012-2013, 2015-2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_ENG_NMEA_H
+#define LOC_ENG_NMEA_H
+
+#include <gps_extended.h>
+#include <vector>
+#include <string>
+#define NMEA_SENTENCE_MAX_LENGTH 200
+
+/** gnss datum type */
+#define LOC_GNSS_DATUM_WGS84 0
+#define LOC_GNSS_DATUM_PZ90 1
+
+/* len of semi major axis of ref ellips*/
+#define MAJA (6378137.0)
+/* flattening coef of ref ellipsoid*/
+#define FLAT (1.0/298.2572235630)
+/* 1st eccentricity squared*/
+#define ESQR (FLAT*(2.0 - FLAT))
+/*1 minus eccentricity squared*/
+#define OMES (1.0 - ESQR)
+#define MILARCSEC2RAD (4.848136811095361e-09)
+/*semi major axis */
+#define C_PZ90A (6378136.0)
+/*semi minor axis */
+#define C_PZ90B (6356751.3618)
+/* Transformation from WGS84 to PZ90
+ * Cx,Cy,Cz,Rs,Rx,Ry,Rz,C_SYS_A,C_SYS_B*/
+const double DatumConstFromWGS84[9] =
+ {+0.003, +0.001, 0.000, (1.0+(0.000*1E-6)), (-0.019*MILARCSEC2RAD),
+ (+0.042*MILARCSEC2RAD), (-0.002*MILARCSEC2RAD), C_PZ90A, C_PZ90B};
+
+/** Represents a LTP*/
+typedef struct {
+ double lat;
+ double lon;
+ double alt;
+} LocLla;
+
+/** Represents a ECEF*/
+typedef struct {
+ double X;
+ double Y;
+ double Z;
+} LocEcef;
+
+void loc_nmea_generate_sv(const GnssSvNotification &svNotify,
+ std::vector<std::string> &nmeaArraystr);
+
+void loc_nmea_generate_pos(const UlpLocation &location,
+ const GpsLocationExtended &locationExtended,
+ const LocationSystemInfo &systemInfo,
+ unsigned char generate_nmea,
+ bool custom_gga_fix_quality,
+ std::vector<std::string> &nmeaArraystr,
+ int& indexOfGGA,
+ bool isTagBlockGroupingEnabled);
+
+#define DEBUG_NMEA_MINSIZE 6
+#define DEBUG_NMEA_MAXSIZE 4096
+inline bool loc_nmea_is_debug(const char* nmea, int length) {
+ return ((nullptr != nmea) &&
+ (length >= DEBUG_NMEA_MINSIZE) && (length <= DEBUG_NMEA_MAXSIZE) &&
+ (nmea[0] == '$') && (nmea[1] == 'P') && (nmea[2] == 'Q') && (nmea[3] == 'W'));
+}
+
+#endif // LOC_ENG_NMEA_H
diff --git a/gps/utils/loc_target.cpp b/gps/utils/loc_target.cpp
new file mode 100644
index 0000000..3ee42e6
--- /dev/null
+++ b/gps/utils/loc_target.cpp
@@ -0,0 +1,249 @@
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <log_util.h>
+#include "loc_target.h"
+#include "loc_log.h"
+#include <loc_pla.h>
+
+#define APQ8064_ID_1 "109"
+#define APQ8064_ID_2 "153"
+#define MPQ8064_ID_1 "130"
+#define MSM8930_ID_1 "142"
+#define MSM8930_ID_2 "116"
+#define APQ8030_ID_1 "157"
+#define APQ8074_ID_1 "184"
+
+#define LINE_LEN 100
+#define STR_LIQUID "Liquid"
+#define STR_SURF "Surf"
+#define STR_MTP "MTP"
+#define STR_APQ "apq"
+#define STR_SDC "sdc" // alternative string for APQ targets
+#define STR_QCS "qcs" // string for Gen9 APQ targets
+#define STR_MSM "msm"
+#define STR_SDM "sdm" // alternative string for MSM targets
+#define STR_APQ_NO_WGR "baseband_apq_nowgr"
+#define STR_AUTO "auto"
+#define IS_STR_END(c) ((c) == '\0' || (c) == '\n' || (c) == '\r')
+#define LENGTH(s) (sizeof(s) - 1)
+#define GPS_CHECK_NO_ERROR 0
+#define GPS_CHECK_NO_GPS_HW 1
+
+static unsigned int gTarget = (unsigned int)-1;
+
+static int read_a_line(const char * file_path, char * line, int line_size)
+{
+ FILE *fp;
+ int result = 0;
+
+ * line = '\0';
+ fp = fopen(file_path, "r" );
+ if( fp == NULL ) {
+ LOC_LOGE("open failed: %s: %s\n", file_path, strerror(errno));
+ result = -1;
+ } else {
+ int len;
+ fgets(line, line_size, fp);
+ len = strlen(line);
+ while ('\n' == line[len-1]) {
+ // If there is a new line at end of string, replace it with NULL
+ line[len-1] = '\0';
+ len--;
+ }
+ len = len < line_size - 1? len : line_size - 1;
+ line[len] = '\0';
+ LOC_LOGD("cat %s: %s", file_path, line);
+ fclose(fp);
+ }
+ return result;
+}
+
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_target_baseband(char *baseband, int array_length)
+{
+ if(baseband && (array_length >= PROPERTY_VALUE_MAX)) {
+ property_get("ro.baseband", baseband, "");
+ LOC_LOGD("%s:%d]: Baseband: %s\n", __func__, __LINE__, baseband);
+ }
+ else {
+ LOC_LOGE("%s:%d]: NULL parameter or array length less than PROPERTY_VALUE_MAX\n",
+ __func__, __LINE__);
+ }
+}
+
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_platform_name(char *platform_name, int array_length)
+{
+ if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) {
+ property_get("ro.board.platform", platform_name, "");
+ LOC_LOGD("%s:%d]: Target name: %s\n", __func__, __LINE__, platform_name);
+ }
+ else {
+ LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n",
+ __func__, __LINE__);
+ }
+}
+
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_auto_platform_name(char *platform_name, int array_length)
+{
+ if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) {
+ property_get("ro.hardware.type", platform_name, "");
+ LOC_LOGD("%s:%d]: Autoplatform name: %s\n", __func__, __LINE__, platform_name);
+ }
+ else {
+ LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n",
+ __func__, __LINE__);
+ }
+}
+
+/*Reads the property ro.config.low_ram to identify if this is a low ram target
+ Returns:
+ 0 if not a low ram target
+ 1 if this is a low ram target
+*/
+int loc_identify_low_ram_target()
+{
+ int ret = 0;
+ char low_ram_target[PROPERTY_VALUE_MAX];
+ property_get("ro.config.low_ram", low_ram_target, "");
+ LOC_LOGd("low ram target: %s\n", low_ram_target);
+ return !(strncmp(low_ram_target, "true", PROPERTY_VALUE_MAX));
+}
+
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+/* Reads the soc_id node and return the soc_id value */
+void loc_get_device_soc_id(char *soc_id_value, int array_length)
+{
+ static const char soc_id[] = "/sys/devices/soc0/soc_id";
+ static const char soc_id_dep[] = "/sys/devices/system/soc/soc0/id";
+ int return_val = 0;
+
+ if (soc_id_value && (array_length >= PROPERTY_VALUE_MAX)) {
+ if (!access(soc_id, F_OK)) {
+ return_val = read_a_line(soc_id, soc_id_value, array_length);
+ } else {
+ return_val = read_a_line(soc_id_dep, soc_id_value, array_length);
+ }
+ if (0 == return_val) {
+ LOC_LOGd("SOC Id value: %s\n", soc_id_value);
+ } else {
+ LOC_LOGe("Unable to read the soc_id value\n");
+ }
+ } else {
+ LOC_LOGe("Null parameter or array length less than PROPERTY_VALUE_MAX\n");
+ }
+}
+
+unsigned int loc_get_target(void)
+{
+ if (gTarget != (unsigned int)-1)
+ return gTarget;
+
+ static const char hw_platform[] = "/sys/devices/soc0/hw_platform";
+ static const char hw_platform_dep[] =
+ "/sys/devices/system/soc/soc0/hw_platform";
+ static const char mdm[] = "/target"; // mdm target we are using
+
+ char rd_hw_platform[LINE_LEN];
+ char rd_id[LINE_LEN];
+ char rd_mdm[LINE_LEN];
+ char baseband[LINE_LEN];
+ char rd_auto_platform[LINE_LEN];
+
+ loc_get_target_baseband(baseband, sizeof(baseband));
+
+ if (!access(hw_platform, F_OK)) {
+ read_a_line(hw_platform, rd_hw_platform, LINE_LEN);
+ } else {
+ read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN);
+ }
+ // Get the soc-id for this device.
+ loc_get_device_soc_id(rd_id, sizeof(rd_id));
+
+ /*check automotive platform*/
+ loc_get_auto_platform_name(rd_auto_platform, sizeof(rd_auto_platform));
+ if( !memcmp(rd_auto_platform, STR_AUTO, LENGTH(STR_AUTO)) )
+ {
+ gTarget = TARGET_AUTO;
+ goto detected;
+ }
+
+ if( !memcmp(baseband, STR_APQ_NO_WGR, LENGTH(STR_APQ_NO_WGR)) ){
+
+ gTarget = TARGET_NO_GNSS;
+ goto detected;
+ }
+
+ if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) ||
+ !memcmp(baseband, STR_SDC, LENGTH(STR_SDC)) ||
+ !memcmp(baseband, STR_QCS, LENGTH(STR_QCS)) ) {
+
+ if( !memcmp(rd_id, MPQ8064_ID_1, LENGTH(MPQ8064_ID_1))
+ && IS_STR_END(rd_id[LENGTH(MPQ8064_ID_1)]) )
+ gTarget = TARGET_NO_GNSS;
+ else
+ gTarget = TARGET_APQ_SA;
+ } else if (((!memcmp(rd_hw_platform, STR_LIQUID, LENGTH(STR_LIQUID))
+ && IS_STR_END(rd_hw_platform[LENGTH(STR_LIQUID)])) ||
+ (!memcmp(rd_hw_platform, STR_SURF, LENGTH(STR_SURF))
+ && IS_STR_END(rd_hw_platform[LENGTH(STR_SURF)])) ||
+ (!memcmp(rd_hw_platform, STR_MTP, LENGTH(STR_MTP))
+ && IS_STR_END(rd_hw_platform[LENGTH(STR_MTP)]))) &&
+ !read_a_line( mdm, rd_mdm, LINE_LEN)) {
+ gTarget = TARGET_MDM;
+ } else if( (!memcmp(rd_id, MSM8930_ID_1, LENGTH(MSM8930_ID_1))
+ && IS_STR_END(rd_id[LENGTH(MSM8930_ID_1)])) ||
+ (!memcmp(rd_id, MSM8930_ID_2, LENGTH(MSM8930_ID_2))
+ && IS_STR_END(rd_id[LENGTH(MSM8930_ID_2)])) ) {
+ gTarget = TARGET_MSM_NO_SSC;
+ } else if ( !memcmp(baseband, STR_MSM, LENGTH(STR_MSM)) ||
+ !memcmp(baseband, STR_SDM, LENGTH(STR_SDM)) ) {
+ gTarget = TARGET_DEFAULT;
+ } else {
+ gTarget = TARGET_UNKNOWN;
+ }
+
+detected:
+ LOC_LOGW("HAL: %s returned %d", __FUNCTION__, gTarget);
+ return gTarget;
+}
diff --git a/gps/utils/loc_target.h b/gps/utils/loc_target.h
new file mode 100644
index 0000000..2dcd895
--- /dev/null
+++ b/gps/utils/loc_target.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef LOC_TARGET_H
+#define LOC_TARGET_H
+#define TARGET_SET(gnss,ssc) ( (gnss<<1)|ssc )
+#define TARGET_DEFAULT TARGET_SET(GNSS_MSM, HAS_SSC)
+#define TARGET_MDM TARGET_SET(GNSS_MDM, HAS_SSC)
+#define TARGET_APQ_SA TARGET_SET(GNSS_GSS, NO_SSC)
+#define TARGET_NO_GNSS TARGET_SET(GNSS_NONE, NO_SSC)
+#define TARGET_MSM_NO_SSC TARGET_SET(GNSS_MSM, NO_SSC)
+#define TARGET_AUTO TARGET_SET(GNSS_AUTO, NO_SSC)
+#define TARGET_UNKNOWN TARGET_SET(GNSS_UNKNOWN, NO_SSC)
+#define getTargetGnssType(target) (target>>1)
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+unsigned int loc_get_target(void);
+
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_target_baseband(char *baseband, int array_length);
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_platform_name(char *platform_name, int array_length);
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_auto_platform_name(char *platform_name, int array_length);
+int loc_identify_low_ram_target();
+/*The character array passed to this function should have length
+ of atleast PROPERTY_VALUE_MAX*/
+void loc_get_device_soc_id(char *soc_id_value, int array_length);
+
+/* Please remember to update 'target_name' in loc_log.cpp,
+ if do any changes to this enum. */
+typedef enum {
+ GNSS_NONE = 0,
+ GNSS_MSM,
+ GNSS_GSS,
+ GNSS_MDM,
+ GNSS_AUTO,
+ GNSS_UNKNOWN
+}GNSS_TARGET;
+
+typedef enum {
+ NO_SSC = 0,
+ HAS_SSC
+}SSC_TYPE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*LOC_TARGET_H*/
diff --git a/gps/utils/loc_timer.h b/gps/utils/loc_timer.h
new file mode 100644
index 0000000..fff0c46
--- /dev/null
+++ b/gps/utils/loc_timer.h
@@ -0,0 +1,74 @@
+/* Copyright (c) 2013,2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __LOC_DELAY_H__
+#define __LOC_DELAY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#include <stddef.h>
+#include <stdint.h>
+#include <loc_pla.h>
+/*
+ user_data: client context pointer, passthrough. Originally received
+ from calling client when loc_timer_start() is called.
+ result: 0 if timer successfully timed out; else timer failed.
+*/
+typedef void (*loc_timer_callback)(void *user_data, int32_t result);
+
+
+/*
+ delay_msec: timeout value for the timer.
+ cb_func: callback function pointer, implemented by client.
+ Can not be NULL.
+ user_data: client context pointer, passthrough. Will be
+ returned when loc_timer_callback() is called.
+ wakeOnExpire: true if to wake up CPU (if sleeping) upon timer
+ expiration and notify the client.
+ false if to wait until next time CPU wakes up (if
+ sleeping) and then notify the client.
+ Returns the handle, which can be used to stop the timer
+ NULL, if timer start fails (e.g. if cb_func is NULL).
+*/
+void* loc_timer_start(uint64_t delay_msec,
+ loc_timer_callback cb_func,
+ void *user_data,
+ bool wake_on_expire=false);
+
+/*
+ handle becomes invalid upon the return of the callback
+*/
+void loc_timer_stop(void*& handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif //__LOC_DELAY_H__
diff --git a/gps/utils/log_util.h b/gps/utils/log_util.h
new file mode 100644
index 0000000..33aa6e2
--- /dev/null
+++ b/gps/utils/log_util.h
@@ -0,0 +1,291 @@
+/* Copyright (c) 2011-2014, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __LOG_UTIL_H__
+#define __LOG_UTIL_H__
+
+#include <stdbool.h>
+#include <loc_pla.h>
+#if defined (USE_ANDROID_LOGGING) || defined (ANDROID)
+// Android and LE targets with logcat support
+#include <utils/Log.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#elif defined (USE_GLIB)
+// LE targets with no logcat support
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "GPS_UTILS"
+#endif /* LOG_TAG */
+
+// LE targets with no logcat support
+#if defined(FEATURE_EXTERNAL_AP) || defined(USE_SYSLOG_LOGGING)
+#include <syslog.h>
+#define ALOGE(...) syslog(LOG_ERR, "LOC_LOGE: " __VA_ARGS__);
+#define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__);
+#define ALOGI(...) syslog(LOG_NOTICE, "LOC_LOGI: " __VA_ARGS__);
+#define ALOGD(...) syslog(LOG_DEBUG, "LOC_LOGD: " __VA_ARGS__);
+#define ALOGV(...) syslog(LOG_NOTICE, "LOC_LOGV: " __VA_ARGS__);
+#else /* FEATURE_EXTERNAL_AP */
+#define TS_PRINTF(format, x...) \
+{ \
+ struct timeval tv; \
+ struct timezone tz; \
+ int hh, mm, ss; \
+ gettimeofday(&tv, &tz); \
+ hh = tv.tv_sec/3600%24; \
+ mm = (tv.tv_sec%3600)/60; \
+ ss = tv.tv_sec%60; \
+ fprintf(stdout,"%02d:%02d:%02d.%06ld]" format "\n", hh, mm, ss, tv.tv_usec, ##x); \
+}
+
+#define ALOGE(format, x...) TS_PRINTF("E/%s (%d): " format , LOG_TAG, getpid(), ##x)
+#define ALOGW(format, x...) TS_PRINTF("W/%s (%d): " format , LOG_TAG, getpid(), ##x)
+#define ALOGI(format, x...) TS_PRINTF("I/%s (%d): " format , LOG_TAG, getpid(), ##x)
+#define ALOGD(format, x...) TS_PRINTF("D/%s (%d): " format , LOG_TAG, getpid(), ##x)
+#define ALOGV(format, x...) TS_PRINTF("V/%s (%d): " format , LOG_TAG, getpid(), ##x)
+#endif /* FEATURE_EXTERNAL_AP */
+
+#endif /* #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*=============================================================================
+ *
+ * LOC LOGGER TYPE DECLARATION
+ *
+ *============================================================================*/
+/* LOC LOGGER */
+typedef struct loc_logger_s
+{
+ unsigned long DEBUG_LEVEL;
+ unsigned long TIMESTAMP;
+ bool LOG_BUFFER_ENABLE;
+} loc_logger_s_type;
+
+
+/*=============================================================================
+ *
+ * EXTERNAL DATA
+ *
+ *============================================================================*/
+
+// Logging Improvements
+extern const char *loc_logger_boolStr[];
+
+extern loc_logger_s_type loc_logger;
+extern const char *boolStr[];
+extern const char VOID_RET[];
+extern const char FROM_AFW[];
+extern const char TO_MODEM[];
+extern const char FROM_MODEM[];
+extern const char TO_AFW[];
+extern const char EXIT_TAG[];
+extern const char ENTRY_TAG[];
+extern const char EXIT_ERROR_TAG[];
+
+#define BUILD_TYPE_PROP_NA 0
+#define BUILD_TYPE_PROP_USER 1
+#define BUILD_TYPE_PROP_USERDEBUG 2
+#define BUILD_TYPE_PROP_INVALID 3
+extern int build_type_prop;
+
+/*=============================================================================
+ *
+ * MODULE EXPORTED FUNCTIONS
+ *
+ *============================================================================*/
+inline void loc_logger_init(unsigned long debug, unsigned long timestamp)
+{
+ loc_logger.DEBUG_LEVEL = debug;
+
+ if (BUILD_TYPE_PROP_NA == build_type_prop) {
+ char value[PROPERTY_VALUE_MAX] = "NA";
+ property_get("ro.build.type", value, "userdebug");
+ if (0 == strcmp(value, "user")) {
+ build_type_prop = BUILD_TYPE_PROP_USER;
+ } else if (0 == strcmp(value, "userdebug")) {
+ build_type_prop = BUILD_TYPE_PROP_USERDEBUG;
+ } else {
+ build_type_prop = BUILD_TYPE_PROP_INVALID;
+ }
+ }
+
+ if (BUILD_TYPE_PROP_USER == build_type_prop) {
+ // force user builds to 2 or less
+ if (loc_logger.DEBUG_LEVEL > 2) {
+ loc_logger.DEBUG_LEVEL = 2;
+ }
+ }
+
+ loc_logger.TIMESTAMP = timestamp;
+}
+
+inline void log_buffer_init(bool enabled) {
+ loc_logger.LOG_BUFFER_ENABLE = enabled;
+}
+extern void log_tag_level_map_init();
+extern int get_tag_log_level(const char* tag);
+extern char* get_timestamp(char* str, unsigned long buf_size);
+extern void log_buffer_insert(char *str, unsigned long buf_size, int level);
+/*=============================================================================
+ *
+ * LOGGING BUFFER MACROS
+ *
+ *============================================================================*/
+#ifndef LOG_NDEBUG
+#define LOG_NDEBUG 0
+#endif
+#define TOTAL_LOG_LEVELS 5
+#define LOGGING_BUFFER_MAX_LEN 1024
+#define IF_LOG_BUFFER_ENABLE if (loc_logger.LOG_BUFFER_ENABLE)
+#define INSERT_BUFFER(flag, level, format, x...) \
+{ \
+ IF_LOG_BUFFER_ENABLE { \
+ if (flag == 0) { \
+ char timestr[32]; \
+ get_timestamp(timestr, sizeof(timestr)); \
+ char log_str[LOGGING_BUFFER_MAX_LEN]; \
+ snprintf(log_str, LOGGING_BUFFER_MAX_LEN, "%s %d %ld %s :" format "\n", \
+ timestr, getpid(), syscall(SYS_gettid), LOG_TAG==NULL ? "": LOG_TAG, ##x);\
+ log_buffer_insert(log_str, sizeof(log_str), level); \
+ } \
+ } \
+}
+
+#ifndef DEBUG_DMN_LOC_API
+
+/* LOGGING MACROS */
+/*loc_logger.DEBUG_LEVEL is initialized to 0xff in loc_cfg.cpp
+ if that value remains unchanged, it means gps.conf did not
+ provide a value and we default to the initial value to use
+ Android's logging levels*/
+
+
+/* Tag based logging control MACROS */
+/* The logic is like this:
+ * 1, LOCAL_LOG_LEVEL is defined as a static variable in log_util.h,
+ * then all source files which includes log_util.h will have its own LOCAL_LOG_LEVEL variable;
+ * 2, For each source file,
+ * 2.1, First time when LOC_LOG* is invoked(its LOCAL_LOG_LEVEL == -1),
+ * Set the tag based log level according to the <tag, level> map;
+ * If this tag isn't found in map, set local debug level as global loc_logger.DEBUG_LEVEL;
+ * 2.2, If not the first time, use its LOCAL_LOG_LEVEL as the debug level of this tag.
+*/
+static int LOCAL_LOG_LEVEL = -1;
+#define IF_LOC_LOG(x) \
+ if (((LOCAL_LOG_LEVEL == -1 && (LOCAL_LOG_LEVEL = get_tag_log_level(LOG_TAG)) >= x) ||\
+ LOCAL_LOG_LEVEL >= x) && LOCAL_LOG_LEVEL <= 5)
+
+#define IF_LOC_LOGE IF_LOC_LOG(1)
+#define IF_LOC_LOGW IF_LOC_LOG(2)
+#define IF_LOC_LOGI IF_LOC_LOG(3)
+#define IF_LOC_LOGD IF_LOC_LOG(4)
+#define IF_LOC_LOGV IF_LOC_LOG(5)
+
+#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);}
+#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);}
+#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 2, __VA_ARGS__);}
+#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 3, __VA_ARGS__);}
+#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 4, __VA_ARGS__);}
+
+#else /* DEBUG_DMN_LOC_API */
+
+#define LOC_LOGE(...) ALOGE(__VA_ARGS__)
+#define LOC_LOGW(...) ALOGW(__VA_ARGS__)
+#define LOC_LOGI(...) ALOGI(__VA_ARGS__)
+#define LOC_LOGD(...) ALOGD(__VA_ARGS__)
+#define LOC_LOGV(...) ALOGV(__VA_ARGS__)
+
+#endif /* DEBUG_DMN_LOC_API */
+
+/*=============================================================================
+ *
+ * LOGGING IMPROVEMENT MACROS
+ *
+ *============================================================================*/
+#define LOG_(LOC_LOG, ID, WHAT, SPEC, VAL) \
+ do { \
+ if (loc_logger.TIMESTAMP) { \
+ char ts[32]; \
+ LOC_LOG("[%s] %s %s line %d " #SPEC, \
+ get_timestamp(ts, sizeof(ts)), ID, WHAT, __LINE__, VAL); \
+ } else { \
+ LOC_LOG("%s %s line %d " #SPEC, \
+ ID, WHAT, __LINE__, VAL); \
+ } \
+ } while(0)
+
+#define LOC_LOG_HEAD(fmt) "%s:%d] " fmt
+#define LOC_LOGv(fmt,...) LOC_LOGV(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define LOC_LOGw(fmt,...) LOC_LOGW(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define LOC_LOGi(fmt,...) LOC_LOGI(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define LOC_LOGd(fmt,...) LOC_LOGD(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define LOC_LOGe(fmt,...) LOC_LOGE(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#define LOG_I(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGI, ID, WHAT, SPEC, VAL)
+#define LOG_V(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGV, ID, WHAT, SPEC, VAL)
+#define LOG_E(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGE, ID, WHAT, SPEC, VAL)
+#define LOG_D(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGD, ID, WHAT, SPEC, VAL)
+
+#define ENTRY_LOG() LOG_V(ENTRY_TAG, __FUNCTION__, %s, "")
+#define EXIT_LOG(SPEC, VAL) LOG_V(EXIT_TAG, __FUNCTION__, SPEC, VAL)
+#define EXIT_LOG_WITH_ERROR(SPEC, VAL) \
+ if (VAL != 0) { \
+ LOG_E(EXIT_ERROR_TAG, __FUNCTION__, SPEC, VAL); \
+ } else { \
+ LOG_V(EXIT_TAG, __FUNCTION__, SPEC, VAL); \
+ }
+
+
+// Used for logging callflow from Android Framework
+#define ENTRY_LOG_CALLFLOW() LOG_I(FROM_AFW, __FUNCTION__, %s, "")
+// Used for logging callflow to Modem
+#define EXIT_LOG_CALLFLOW(SPEC, VAL) LOG_I(TO_MODEM, __FUNCTION__, SPEC, VAL)
+// Used for logging callflow from Modem(TO_MODEM, __FUNCTION__, %s, "")
+#define MODEM_LOG_CALLFLOW(SPEC, VAL) LOG_I(FROM_MODEM, __FUNCTION__, SPEC, VAL)
+// Used for logging high frequency callflow from Modem(TO_MODEM, __FUNCTION__, %s, "")
+#define MODEM_LOG_CALLFLOW_DEBUG(SPEC, VAL) LOG_D(FROM_MODEM, __FUNCTION__, SPEC, VAL)
+// Used for logging callflow to Android Framework
+#define CALLBACK_LOG_CALLFLOW(CB, SPEC, VAL) LOG_I(TO_AFW, CB, SPEC, VAL)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LOG_UTIL_H__
diff --git a/gps/utils/msg_q.c b/gps/utils/msg_q.c
new file mode 100644
index 0000000..3383960
--- /dev/null
+++ b/gps/utils/msg_q.c
@@ -0,0 +1,380 @@
+/* Copyright (c) 2011-2012, 2014, 2017 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Uncomment to log verbose logs
+#define LOG_NDEBUG 1
+#define LOG_TAG "LocSvc_utils_q"
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <loc_pla.h>
+#include <log_util.h>
+#include "linked_list.h"
+#include "msg_q.h"
+
+typedef struct msg_q {
+ void* msg_list; /* Linked list to store information */
+ pthread_cond_t list_cond; /* Condition variable for waiting on msg queue */
+ pthread_mutex_t list_mutex; /* Mutex for exclusive access to message queue */
+ int unblocked; /* Has this message queue been unblocked? */
+} msg_q;
+
+/*===========================================================================
+FUNCTION convert_linked_list_err_type
+
+DESCRIPTION
+ Converts from one set of enum values to another.
+
+ linked_list_val: Value to convert to msg_q_enum_type
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Corresponding linked_list_enum_type in msg_q_enum_type
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+static msq_q_err_type convert_linked_list_err_type(linked_list_err_type linked_list_val)
+{
+ switch( linked_list_val )
+ {
+ case eLINKED_LIST_SUCCESS:
+ return eMSG_Q_SUCCESS;
+ case eLINKED_LIST_INVALID_PARAMETER:
+ return eMSG_Q_INVALID_PARAMETER;
+ case eLINKED_LIST_INVALID_HANDLE:
+ return eMSG_Q_INVALID_HANDLE;
+ case eLINKED_LIST_UNAVAILABLE_RESOURCE:
+ return eMSG_Q_UNAVAILABLE_RESOURCE;
+ case eLINKED_LIST_INSUFFICIENT_BUFFER:
+ return eMSG_Q_INSUFFICIENT_BUFFER;
+
+ case eLINKED_LIST_FAILURE_GENERAL:
+ default:
+ return eMSG_Q_FAILURE_GENERAL;
+ }
+}
+
+/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */
+
+/*===========================================================================
+
+ FUNCTION: msg_q_init
+
+ ===========================================================================*/
+msq_q_err_type msg_q_init(void** msg_q_data)
+{
+ if( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_PARAMETER;
+ }
+
+ msg_q* tmp_msg_q;
+ tmp_msg_q = (msg_q*)calloc(1, sizeof(msg_q));
+ if( tmp_msg_q == NULL )
+ {
+ LOC_LOGE("%s: Unable to allocate space for message queue!\n", __FUNCTION__);
+ return eMSG_Q_FAILURE_GENERAL;
+ }
+
+ if( linked_list_init(&tmp_msg_q->msg_list) != 0 )
+ {
+ LOC_LOGE("%s: Unable to initialize storage list!\n", __FUNCTION__);
+ free(tmp_msg_q);
+ return eMSG_Q_FAILURE_GENERAL;
+ }
+
+ if( pthread_mutex_init(&tmp_msg_q->list_mutex, NULL) != 0 )
+ {
+ LOC_LOGE("%s: Unable to initialize list mutex!\n", __FUNCTION__);
+ linked_list_destroy(&tmp_msg_q->msg_list);
+ free(tmp_msg_q);
+ return eMSG_Q_FAILURE_GENERAL;
+ }
+
+ if( pthread_cond_init(&tmp_msg_q->list_cond, NULL) != 0 )
+ {
+ LOC_LOGE("%s: Unable to initialize msg q cond var!\n", __FUNCTION__);
+ linked_list_destroy(&tmp_msg_q->msg_list);
+ pthread_mutex_destroy(&tmp_msg_q->list_mutex);
+ free(tmp_msg_q);
+ return eMSG_Q_FAILURE_GENERAL;
+ }
+
+ tmp_msg_q->unblocked = 0;
+
+ *msg_q_data = tmp_msg_q;
+
+ return eMSG_Q_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_init2
+
+ ===========================================================================*/
+const void* msg_q_init2()
+{
+ void* q = NULL;
+ if (eMSG_Q_SUCCESS != msg_q_init(&q)) {
+ q = NULL;
+ }
+ return q;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_destroy
+
+ ===========================================================================*/
+msq_q_err_type msg_q_destroy(void** msg_q_data)
+{
+ if( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+
+ msg_q* p_msg_q = (msg_q*)*msg_q_data;
+
+ linked_list_destroy(&p_msg_q->msg_list);
+ pthread_mutex_destroy(&p_msg_q->list_mutex);
+ pthread_cond_destroy(&p_msg_q->list_cond);
+
+ p_msg_q->unblocked = 0;
+
+ free(*msg_q_data);
+ *msg_q_data = NULL;
+
+ return eMSG_Q_SUCCESS;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_snd
+
+ ===========================================================================*/
+msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*))
+{
+ msq_q_err_type rv;
+ if( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+ if( msg_obj == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_PARAMETER;
+ }
+
+ msg_q* p_msg_q = (msg_q*)msg_q_data;
+
+ pthread_mutex_lock(&p_msg_q->list_mutex);
+ LOC_LOGV("%s: Sending message with handle = %p\n", __FUNCTION__, msg_obj);
+
+ if( p_msg_q->unblocked )
+ {
+ LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+ return eMSG_Q_UNAVAILABLE_RESOURCE;
+ }
+
+ rv = convert_linked_list_err_type(linked_list_add(p_msg_q->msg_list, msg_obj, dealloc));
+
+ /* Show data is in the message queue. */
+ pthread_cond_signal(&p_msg_q->list_cond);
+
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+
+ LOC_LOGV("%s: Finished Sending message with handle = %p\n", __FUNCTION__, msg_obj);
+
+ return rv;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_rcv
+
+ ===========================================================================*/
+msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj)
+{
+ msq_q_err_type rv;
+ if( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+
+ if( msg_obj == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_PARAMETER;
+ }
+
+ msg_q* p_msg_q = (msg_q*)msg_q_data;
+
+ pthread_mutex_lock(&p_msg_q->list_mutex);
+
+ if( p_msg_q->unblocked )
+ {
+ LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+ return eMSG_Q_UNAVAILABLE_RESOURCE;
+ }
+
+ /* Wait for data in the message queue */
+ while( linked_list_empty(p_msg_q->msg_list) && !p_msg_q->unblocked )
+ {
+ pthread_cond_wait(&p_msg_q->list_cond, &p_msg_q->list_mutex);
+ }
+
+ rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
+
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+
+ LOC_LOGV("%s: Received message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
+
+ return rv;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_rmv
+
+ ===========================================================================*/
+msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj)
+{
+ msq_q_err_type rv;
+ if (msg_q_data == NULL) {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+
+ if (msg_obj == NULL) {
+ LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_PARAMETER;
+ }
+
+ msg_q* p_msg_q = (msg_q*)msg_q_data;
+
+ pthread_mutex_lock(&p_msg_q->list_mutex);
+
+ if (p_msg_q->unblocked) {
+ LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+ return eMSG_Q_UNAVAILABLE_RESOURCE;
+ }
+
+ if (linked_list_empty(p_msg_q->msg_list)) {
+ LOC_LOGW("%s: list is empty !!\n", __FUNCTION__);
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+ return eLINKED_LIST_EMPTY;
+ }
+
+ rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
+
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+
+ LOC_LOGV("%s: Removed message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
+
+ return rv;
+}
+
+
+
+/*===========================================================================
+
+ FUNCTION: msg_q_flush
+
+ ===========================================================================*/
+msq_q_err_type msg_q_flush(void* msg_q_data)
+{
+ msq_q_err_type rv;
+ if ( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+
+ msg_q* p_msg_q = (msg_q*)msg_q_data;
+
+ LOC_LOGD("%s: Flushing Message Queue\n", __FUNCTION__);
+
+ pthread_mutex_lock(&p_msg_q->list_mutex);
+
+ /* Remove all elements from the list */
+ rv = convert_linked_list_err_type(linked_list_flush(p_msg_q->msg_list));
+
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+
+ LOC_LOGD("%s: Message Queue flushed\n", __FUNCTION__);
+
+ return rv;
+}
+
+/*===========================================================================
+
+ FUNCTION: msg_q_unblock
+
+ ===========================================================================*/
+msq_q_err_type msg_q_unblock(void* msg_q_data)
+{
+ if ( msg_q_data == NULL )
+ {
+ LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
+ return eMSG_Q_INVALID_HANDLE;
+ }
+
+ msg_q* p_msg_q = (msg_q*)msg_q_data;
+ pthread_mutex_lock(&p_msg_q->list_mutex);
+
+ if( p_msg_q->unblocked )
+ {
+ LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+ return eMSG_Q_UNAVAILABLE_RESOURCE;
+ }
+
+ LOC_LOGD("%s: Unblocking Message Queue\n", __FUNCTION__);
+ /* Unblocking message queue */
+ p_msg_q->unblocked = 1;
+
+ /* Allow all the waiters to wake up */
+ pthread_cond_broadcast(&p_msg_q->list_cond);
+
+ pthread_mutex_unlock(&p_msg_q->list_mutex);
+
+ LOC_LOGD("%s: Message Queue unblocked\n", __FUNCTION__);
+
+ return eMSG_Q_SUCCESS;
+}
diff --git a/gps/utils/msg_q.h b/gps/utils/msg_q.h
new file mode 100644
index 0000000..16df494
--- /dev/null
+++ b/gps/utils/msg_q.h
@@ -0,0 +1,230 @@
+/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MSG_Q_H__
+#define __MSG_Q_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdlib.h>
+
+/** Linked List Return Codes */
+typedef enum
+{
+ eMSG_Q_SUCCESS = 0,
+ /**< Request was successful. */
+ eMSG_Q_FAILURE_GENERAL = -1,
+ /**< Failed because of a general failure. */
+ eMSG_Q_INVALID_PARAMETER = -2,
+ /**< Failed because the request contained invalid parameters. */
+ eMSG_Q_INVALID_HANDLE = -3,
+ /**< Failed because an invalid handle was specified. */
+ eMSG_Q_UNAVAILABLE_RESOURCE = -4,
+ /**< Failed because an there were not enough resources. */
+ eMSG_Q_INSUFFICIENT_BUFFER = -5,
+ /**< Failed because an the supplied buffer was too small. */
+}msq_q_err_type;
+
+/*===========================================================================
+FUNCTION msg_q_init
+
+DESCRIPTION
+ Initializes internal structures for message queue.
+
+ msg_q_data: pointer to an opaque Q handle to be returned; NULL if fails
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_init(void** msg_q_data);
+
+/*===========================================================================
+FUNCTION msg_q_init2
+
+DESCRIPTION
+ Initializes internal structures for message queue.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ opaque handle to the Q created; NULL if create fails
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+const void* msg_q_init2();
+
+/*===========================================================================
+FUNCTION msg_q_destroy
+
+DESCRIPTION
+ Releases internal structures for message queue.
+
+ msg_q_data: State of message queue to be released.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_destroy(void** msg_q_data);
+
+/*===========================================================================
+FUNCTION msg_q_snd
+
+DESCRIPTION
+ Sends data to the message queue. The passed in data pointer
+ is not modified or freed. Passed in msg_obj is expected to live throughout
+ the use of the msg_q (i.e. data is not allocated internally)
+
+ msg_q_data: Message Queue to add the element to.
+ msgp: Pointer to data to add into message queue.
+ dealloc: Function used to deallocate memory for this element. Pass NULL
+ if you do not want data deallocated during a flush operation
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*));
+
+/*===========================================================================
+FUNCTION msg_q_rcv
+
+DESCRIPTION
+ Retrieves data from the message queue. msg_obj is the oldest message received
+ and pointer is simply removed from message queue.
+
+ msg_q_data: Message Queue to copy data from into msgp.
+ msg_obj: Pointer to space to copy msg_q contents to.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj);
+
+/*===========================================================================
+FUNCTION msg_q_rmv
+
+DESCRIPTION
+ Remove data from the message queue. msg_obj is the oldest message received
+ and pointer is simply removed from message queue.
+
+ msg_q_data: Message Queue to copy data from into msgp.
+ msg_obj: Pointer to space to copy msg_q contents to.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj);
+
+
+/*===========================================================================
+FUNCTION msg_q_flush
+
+DESCRIPTION
+ Function removes all elements from the message queue.
+
+ msg_q_data: Message Queue to remove elements from.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_flush(void* msg_q_data);
+
+/*===========================================================================
+FUNCTION msg_q_unblock
+
+DESCRIPTION
+ This function will stop use of the message queue. All waiters will wake up
+ and likely receive nothing from the queue resulting in a negative return
+ value. The message queue can no longer be used until it is destroyed
+ and initialized again after calling this function.
+
+ msg_q_data: Message queue to unblock.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Look at error codes above.
+
+SIDE EFFECTS
+ N/A
+
+===========================================================================*/
+msq_q_err_type msg_q_unblock(void* msg_q_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MSG_Q_H__ */