From 86a968c3f424cb70e03cccb24cabf9751f6f636d Mon Sep 17 00:00:00 2001 From: Raghuram Subramani Date: Mon, 14 Oct 2024 20:38:19 +0530 Subject: update gps stack --- BoardConfigCommon.mk | 5 +- gps/Android.mk | 1 - gps/CleanSpec.mk | 50 - gps/Makefile.am | 10 - gps/android/1.0/AGnss.cpp | 203 + gps/android/1.0/AGnss.h | 79 + gps/android/1.0/AGnssRil.cpp | 114 + gps/android/1.0/AGnssRil.h | 83 + gps/android/1.0/Android.mk | 99 + gps/android/1.0/Gnss.cpp | 360 ++ gps/android/1.0/Gnss.h | 143 + gps/android/1.0/GnssBatching.cpp | 130 + gps/android/1.0/GnssBatching.h | 80 + gps/android/1.0/GnssConfiguration.cpp | 230 ++ gps/android/1.0/GnssConfiguration.h | 71 + gps/android/1.0/GnssDebug.cpp | 173 + gps/android/1.0/GnssDebug.h | 59 + gps/android/1.0/GnssGeofencing.cpp | 141 + gps/android/1.0/GnssGeofencing.h | 91 + gps/android/1.0/GnssMeasurement.cpp | 101 + gps/android/1.0/GnssMeasurement.h | 77 + gps/android/1.0/GnssNi.cpp | 85 + gps/android/1.0/GnssNi.h | 75 + .../1.0/android.hardware.gnss@1.0-service-qti.rc | 4 + .../1.0/android.hardware.gnss@1.0-service-qti.xml | 35 + gps/android/1.0/location_api/BatchingAPIClient.cpp | 196 + gps/android/1.0/location_api/BatchingAPIClient.h | 74 + gps/android/1.0/location_api/GeofenceAPIClient.cpp | 275 ++ gps/android/1.0/location_api/GeofenceAPIClient.h | 76 + gps/android/1.0/location_api/GnssAPIClient.cpp | 566 +++ gps/android/1.0/location_api/GnssAPIClient.h | 109 + gps/android/1.0/location_api/LocationUtil.cpp | 206 + gps/android/1.0/location_api/LocationUtil.h | 55 + .../1.0/location_api/MeasurementAPIClient.cpp | 276 ++ .../1.0/location_api/MeasurementAPIClient.h | 77 + gps/android/1.0/service.cpp | 85 + gps/android/1.1/AGnss.cpp | 203 + gps/android/1.1/AGnss.h | 79 + gps/android/1.1/AGnssRil.cpp | 114 + gps/android/1.1/AGnssRil.h | 83 + gps/android/1.1/Android.mk | 101 + gps/android/1.1/Gnss.cpp | 477 +++ gps/android/1.1/Gnss.h | 154 + gps/android/1.1/GnssBatching.cpp | 130 + gps/android/1.1/GnssBatching.h | 80 + gps/android/1.1/GnssConfiguration.cpp | 313 ++ gps/android/1.1/GnssConfiguration.h | 78 + gps/android/1.1/GnssDebug.cpp | 175 + gps/android/1.1/GnssDebug.h | 59 + gps/android/1.1/GnssGeofencing.cpp | 141 + gps/android/1.1/GnssGeofencing.h | 91 + gps/android/1.1/GnssMeasurement.cpp | 134 + gps/android/1.1/GnssMeasurement.h | 83 + gps/android/1.1/GnssNi.cpp | 85 + gps/android/1.1/GnssNi.h | 75 + .../1.1/android.hardware.gnss@1.1-service-qti.rc | 4 + .../1.1/android.hardware.gnss@1.1-service-qti.xml | 35 + gps/android/1.1/location_api/BatchingAPIClient.cpp | 196 + gps/android/1.1/location_api/BatchingAPIClient.h | 74 + gps/android/1.1/location_api/GeofenceAPIClient.cpp | 275 ++ gps/android/1.1/location_api/GeofenceAPIClient.h | 76 + gps/android/1.1/location_api/GnssAPIClient.cpp | 566 +++ gps/android/1.1/location_api/GnssAPIClient.h | 109 + gps/android/1.1/location_api/LocationUtil.cpp | 206 + gps/android/1.1/location_api/LocationUtil.h | 55 + .../1.1/location_api/MeasurementAPIClient.cpp | 332 ++ .../1.1/location_api/MeasurementAPIClient.h | 84 + gps/android/1.1/service.cpp | 85 + gps/android/2.0/AGnss.cpp | 209 ++ gps/android/2.0/AGnss.h | 77 + gps/android/2.0/AGnssRil.cpp | 133 + gps/android/2.0/AGnssRil.h | 84 + gps/android/2.0/Android.mk | 112 + gps/android/2.0/Gnss.cpp | 671 ++++ gps/android/2.0/Gnss.h | 187 + gps/android/2.0/GnssBatching.cpp | 163 + gps/android/2.0/GnssBatching.h | 84 + gps/android/2.0/GnssConfiguration.cpp | 321 ++ gps/android/2.0/GnssConfiguration.h | 80 + gps/android/2.0/GnssDebug.cpp | 299 ++ gps/android/2.0/GnssDebug.h | 62 + gps/android/2.0/GnssGeofencing.cpp | 141 + gps/android/2.0/GnssGeofencing.h | 91 + gps/android/2.0/GnssMeasurement.cpp | 165 + gps/android/2.0/GnssMeasurement.h | 86 + gps/android/2.0/GnssNi.cpp | 85 + gps/android/2.0/GnssNi.h | 75 + .../2.0/android.hardware.gnss@2.0-service-qti.rc | 4 + .../2.0/android.hardware.gnss@2.0-service-qti.xml | 36 + gps/android/2.0/location_api/BatchingAPIClient.cpp | 250 ++ gps/android/2.0/location_api/BatchingAPIClient.h | 81 + gps/android/2.0/location_api/GeofenceAPIClient.cpp | 275 ++ gps/android/2.0/location_api/GeofenceAPIClient.h | 76 + gps/android/2.0/location_api/GnssAPIClient.cpp | 728 ++++ gps/android/2.0/location_api/GnssAPIClient.h | 114 + gps/android/2.0/location_api/LocationUtil.cpp | 311 ++ gps/android/2.0/location_api/LocationUtil.h | 58 + .../2.0/location_api/MeasurementAPIClient.cpp | 474 +++ .../2.0/location_api/MeasurementAPIClient.h | 89 + gps/android/2.0/service.cpp | 85 + gps/android/AGnss.cpp | 203 - gps/android/AGnss.h | 79 - gps/android/AGnssRil.cpp | 93 - gps/android/AGnssRil.h | 83 - gps/android/Android.mk | 98 +- gps/android/Gnss.cpp | 343 -- gps/android/Gnss.h | 143 - gps/android/GnssBatching.cpp | 130 - gps/android/GnssBatching.h | 80 - gps/android/GnssConfiguration.cpp | 227 -- gps/android/GnssConfiguration.h | 71 - gps/android/GnssDebug.cpp | 190 - gps/android/GnssDebug.h | 59 - gps/android/GnssGeofencing.cpp | 141 - gps/android/GnssGeofencing.h | 91 - gps/android/GnssMeasurement.cpp | 101 - gps/android/GnssMeasurement.h | 77 - gps/android/GnssNi.cpp | 85 - gps/android/GnssNi.h | 75 - .../android.hardware.gnss@1.0-service-qti.rc | 4 - gps/android/location_api/BatchingAPIClient.cpp | 196 - gps/android/location_api/BatchingAPIClient.h | 74 - gps/android/location_api/GeofenceAPIClient.cpp | 275 -- gps/android/location_api/GeofenceAPIClient.h | 76 - gps/android/location_api/GnssAPIClient.cpp | 537 --- gps/android/location_api/GnssAPIClient.h | 108 - gps/android/location_api/LocationUtil.cpp | 188 - gps/android/location_api/LocationUtil.h | 55 - gps/android/location_api/MeasurementAPIClient.cpp | 275 -- gps/android/location_api/MeasurementAPIClient.h | 76 - .../1.0/MeasurementCorrections.cpp | 71 + .../1.0/MeasurementCorrections.h | 76 + gps/android/service.cpp | 31 - gps/android/utils/Android.mk | 38 + gps/android/utils/battery_listener.cpp | 273 ++ gps/android/utils/battery_listener.h | 32 + .../1.0/GnssVisibilityControl.cpp | 169 + .../visibility_control/1.0/GnssVisibilityControl.h | 90 + gps/batching/Android.mk | 39 + gps/batching/BatchingAdapter.cpp | 1050 ++++++ gps/batching/BatchingAdapter.h | 152 + gps/batching/location_batching.cpp | 134 + gps/build/target_specific_features.mk | 72 +- gps/configure.ac | 87 - gps/core/Android.mk | 11 +- gps/core/ContextBase.cpp | 236 +- gps/core/ContextBase.h | 142 +- gps/core/EngineHubProxyBase.h | 127 + gps/core/LBSProxyBase.h | 12 +- gps/core/LocAdapterBase.cpp | 283 +- gps/core/LocAdapterBase.h | 119 +- gps/core/LocAdapterProxyBase.h | 5 +- gps/core/LocApiBase.cpp | 583 ++- gps/core/LocApiBase.h | 323 +- gps/core/LocContext.cpp | 98 + gps/core/LocContext.h | 66 + gps/core/LocDualContext.cpp | 150 - gps/core/LocDualContext.h | 76 - gps/core/Makefile.am | 66 - gps/core/SystemStatus.cpp | 77 +- gps/core/SystemStatus.h | 149 +- gps/core/SystemStatusOsObserver.cpp | 20 +- gps/core/UlpProxyBase.h | 124 - gps/core/configure.ac | 82 - gps/core/data-items/DataItemConcreteTypesBase.h | 88 +- gps/core/loc-core.pc.in | 10 - gps/core/loc_core_log.cpp | 7 +- gps/core/observer/IOsObserver.h | 4 +- gps/etc/flp.conf | 60 + gps/etc/gps.conf | 306 ++ gps/etc/izat.conf | 247 ++ gps/etc/lowi.conf | 27 + gps/etc/sap.conf | 161 + gps/etc/xtwifi.conf | 78 + gps/geofence/Android.mk | 38 + gps/geofence/GeofenceAdapter.cpp | 870 +++++ gps/geofence/GeofenceAdapter.h | 136 + gps/geofence/location_geofence.cpp | 145 + gps/gnss/Agps.cpp | 337 +- gps/gnss/Agps.h | 133 +- gps/gnss/Android.mk | 3 + gps/gnss/GnssAdapter.cpp | 3916 ++++++++++++++------ gps/gnss/GnssAdapter.h | 298 +- gps/gnss/Makefile.am | 31 - gps/gnss/XtraSystemStatusObserver.cpp | 164 +- gps/gnss/XtraSystemStatusObserver.h | 39 +- gps/gnss/location_gnss.cpp | 135 +- gps/gnsspps/Android.mk | 3 + gps/gnsspps/Makefile.am | 37 - gps/gnsspps/configure.ac | 70 - gps/gnsspps/gnsspps.c | 231 +- gps/gnsspps/gnsspps.pc.in | 10 - gps/loc-hal.pc.in | 10 - gps/location/Android.mk | 3 + gps/location/ILocationAPI.h | 194 + gps/location/LocationAPI.cpp | 326 +- gps/location/LocationAPI.h | 816 +--- gps/location/LocationAPIClientBase.cpp | 122 +- gps/location/LocationAPIClientBase.h | 47 +- gps/location/LocationDataTypes.h | 1465 ++++++++ gps/location/Makefile.am | 38 - gps/location/configure.ac | 82 - gps/location/location-api.pc.in | 10 - gps/location/location_interface.h | 54 +- gps/pla/Android.mk | 15 +- gps/pla/android/loc_pla.h | 8 + gps/pla/oe/loc_pla.h | 35 +- gps/utils/Android.mk | 4 + gps/utils/LocIpc.cpp | 481 ++- gps/utils/LocIpc.h | 209 +- gps/utils/LocSharedLock.h | 20 +- gps/utils/LocThread.cpp | 4 +- gps/utils/Makefile.am | 70 - gps/utils/MsgTask.cpp | 7 +- gps/utils/configure.ac | 82 - gps/utils/gps-utils.pc.in | 10 - gps/utils/gps_extended.h | 14 +- gps/utils/gps_extended_c.h | 1362 +++++-- gps/utils/linked_list.h | 2 + gps/utils/loc_cfg.cpp | 317 +- gps/utils/loc_cfg.h | 23 +- gps/utils/loc_gps.h | 22 +- gps/utils/loc_misc_utils.cpp | 31 + gps/utils/loc_misc_utils.h | 28 + gps/utils/loc_nmea.cpp | 1347 ++++++- gps/utils/loc_nmea.h | 39 + gps/utils/loc_target.cpp | 57 +- gps/utils/loc_target.h | 4 + gps/utils/log_util.h | 33 +- gps/utils/msg_q.c | 45 + gps/utils/msg_q.h | 23 + manifest.xml | 18 - msm8996.mk | 14 +- wifi/wifi_legacy_service/1.0-legacy/Android.bp | 182 + .../1.0-legacy/THREADING.README | 35 + ...ndroid.hardware.wifi@1.0-service.legacy-lazy.rc | 14 + .../android.hardware.wifi@1.0-service.legacy.rc | 12 + .../android.hardware.wifi@1.0-service.legacy.xml | 11 + .../1.0-legacy/hal_legacy/AudioHardwareBase.h | 66 + .../1.0-legacy/hal_legacy/AudioHardwareInterface.h | 296 ++ .../1.0-legacy/hal_legacy/AudioPolicyInterface.h | 249 ++ .../1.0-legacy/hal_legacy/AudioPolicyManagerBase.h | 567 +++ .../1.0-legacy/hal_legacy/AudioSystemLegacy.h | 358 ++ .../1.0-legacy/hal_legacy/IMountService.h | 65 + .../1.0-legacy/hal_legacy/audio_policy_conf.h | 54 + .../1.0-legacy/hal_legacy/gscan.h | 427 +++ .../1.0-legacy/hal_legacy/link_layer_stats.h | 285 ++ .../1.0-legacy/hal_legacy/power.h | 40 + .../1.0-legacy/hal_legacy/roam.h | 57 + .../1.0-legacy/hal_legacy/rtt.h | 314 ++ .../1.0-legacy/hal_legacy/tdls.h | 84 + .../1.0-legacy/hal_legacy/uevent.h | 35 + .../hal_legacy/wifi_cached_scan_results.h | 92 + .../1.0-legacy/hal_legacy/wifi_config.h | 44 + .../1.0-legacy/hal_legacy/wifi_hal.h | 1020 +++++ .../1.0-legacy/hal_legacy/wifi_logger.h | 650 ++++ .../1.0-legacy/hal_legacy/wifi_nan.h | 2726 ++++++++++++++ .../1.0-legacy/hal_legacy/wifi_offload.h | 30 + .../1.0-legacy/hal_legacy/wifi_twt.h | 156 + .../1.0-legacy/hidl_callback_util.h | 122 + .../1.0-legacy/hidl_return_util.h | 118 + .../1.0-legacy/hidl_struct_util.cpp | 3007 +++++++++++++++ .../1.0-legacy/hidl_struct_util.h | 204 + .../1.0-legacy/hidl_sync_util.cpp | 39 + .../1.0-legacy/hidl_sync_util.h | 37 + wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp | 64 + wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h | 62 + wifi/wifi_legacy_service/1.0-legacy/service.cpp | 71 + wifi/wifi_legacy_service/1.0-legacy/wifi.cpp | 294 ++ wifi/wifi_legacy_service/1.0-legacy/wifi.h | 105 + .../1.0-legacy/wifi_ap_iface.cpp | 204 + .../wifi_legacy_service/1.0-legacy/wifi_ap_iface.h | 89 + wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp | 2109 +++++++++++ wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h | 322 ++ .../1.0-legacy/wifi_feature_flags.cpp | 247 ++ .../1.0-legacy/wifi_feature_flags.h | 58 + .../1.0-legacy/wifi_iface_util.cpp | 176 + .../1.0-legacy/wifi_iface_util.h | 87 + .../1.0-legacy/wifi_legacy_hal.cpp | 1654 +++++++++ .../1.0-legacy/wifi_legacy_hal.h | 739 ++++ .../1.0-legacy/wifi_legacy_hal_factory.cpp | 254 ++ .../1.0-legacy/wifi_legacy_hal_factory.h | 66 + .../1.0-legacy/wifi_legacy_hal_stubs.cpp | 178 + .../1.0-legacy/wifi_legacy_hal_stubs.h | 37 + .../1.0-legacy/wifi_mode_controller.cpp | 89 + .../1.0-legacy/wifi_mode_controller.h | 63 + .../1.0-legacy/wifi_nan_iface.cpp | 1018 +++++ .../1.0-legacy/wifi_nan_iface.h | 208 ++ .../1.0-legacy/wifi_p2p_iface.cpp | 69 + .../1.0-legacy/wifi_p2p_iface.h | 66 + .../1.0-legacy/wifi_rtt_controller.cpp | 377 ++ .../1.0-legacy/wifi_rtt_controller.h | 138 + .../1.0-legacy/wifi_sta_iface.cpp | 592 +++ .../1.0-legacy/wifi_sta_iface.h | 157 + .../1.0-legacy/wifi_status_util.cpp | 106 + .../1.0-legacy/wifi_status_util.h | 44 + 296 files changed, 51135 insertions(+), 9327 deletions(-) delete mode 100644 gps/CleanSpec.mk delete mode 100644 gps/Makefile.am create mode 100644 gps/android/1.0/AGnss.cpp create mode 100644 gps/android/1.0/AGnss.h create mode 100644 gps/android/1.0/AGnssRil.cpp create mode 100644 gps/android/1.0/AGnssRil.h create mode 100644 gps/android/1.0/Android.mk create mode 100644 gps/android/1.0/Gnss.cpp create mode 100644 gps/android/1.0/Gnss.h create mode 100644 gps/android/1.0/GnssBatching.cpp create mode 100644 gps/android/1.0/GnssBatching.h create mode 100644 gps/android/1.0/GnssConfiguration.cpp create mode 100644 gps/android/1.0/GnssConfiguration.h create mode 100644 gps/android/1.0/GnssDebug.cpp create mode 100644 gps/android/1.0/GnssDebug.h create mode 100644 gps/android/1.0/GnssGeofencing.cpp create mode 100644 gps/android/1.0/GnssGeofencing.h create mode 100644 gps/android/1.0/GnssMeasurement.cpp create mode 100644 gps/android/1.0/GnssMeasurement.h create mode 100644 gps/android/1.0/GnssNi.cpp create mode 100644 gps/android/1.0/GnssNi.h create mode 100644 gps/android/1.0/android.hardware.gnss@1.0-service-qti.rc create mode 100644 gps/android/1.0/android.hardware.gnss@1.0-service-qti.xml create mode 100644 gps/android/1.0/location_api/BatchingAPIClient.cpp create mode 100644 gps/android/1.0/location_api/BatchingAPIClient.h create mode 100644 gps/android/1.0/location_api/GeofenceAPIClient.cpp create mode 100644 gps/android/1.0/location_api/GeofenceAPIClient.h create mode 100644 gps/android/1.0/location_api/GnssAPIClient.cpp create mode 100644 gps/android/1.0/location_api/GnssAPIClient.h create mode 100644 gps/android/1.0/location_api/LocationUtil.cpp create mode 100644 gps/android/1.0/location_api/LocationUtil.h create mode 100644 gps/android/1.0/location_api/MeasurementAPIClient.cpp create mode 100644 gps/android/1.0/location_api/MeasurementAPIClient.h create mode 100644 gps/android/1.0/service.cpp create mode 100644 gps/android/1.1/AGnss.cpp create mode 100644 gps/android/1.1/AGnss.h create mode 100644 gps/android/1.1/AGnssRil.cpp create mode 100644 gps/android/1.1/AGnssRil.h create mode 100644 gps/android/1.1/Android.mk create mode 100644 gps/android/1.1/Gnss.cpp create mode 100644 gps/android/1.1/Gnss.h create mode 100644 gps/android/1.1/GnssBatching.cpp create mode 100644 gps/android/1.1/GnssBatching.h create mode 100644 gps/android/1.1/GnssConfiguration.cpp create mode 100644 gps/android/1.1/GnssConfiguration.h create mode 100644 gps/android/1.1/GnssDebug.cpp create mode 100644 gps/android/1.1/GnssDebug.h create mode 100644 gps/android/1.1/GnssGeofencing.cpp create mode 100644 gps/android/1.1/GnssGeofencing.h create mode 100644 gps/android/1.1/GnssMeasurement.cpp create mode 100644 gps/android/1.1/GnssMeasurement.h create mode 100644 gps/android/1.1/GnssNi.cpp create mode 100644 gps/android/1.1/GnssNi.h create mode 100644 gps/android/1.1/android.hardware.gnss@1.1-service-qti.rc create mode 100644 gps/android/1.1/android.hardware.gnss@1.1-service-qti.xml create mode 100644 gps/android/1.1/location_api/BatchingAPIClient.cpp create mode 100644 gps/android/1.1/location_api/BatchingAPIClient.h create mode 100644 gps/android/1.1/location_api/GeofenceAPIClient.cpp create mode 100644 gps/android/1.1/location_api/GeofenceAPIClient.h create mode 100644 gps/android/1.1/location_api/GnssAPIClient.cpp create mode 100644 gps/android/1.1/location_api/GnssAPIClient.h create mode 100644 gps/android/1.1/location_api/LocationUtil.cpp create mode 100644 gps/android/1.1/location_api/LocationUtil.h create mode 100644 gps/android/1.1/location_api/MeasurementAPIClient.cpp create mode 100644 gps/android/1.1/location_api/MeasurementAPIClient.h create mode 100644 gps/android/1.1/service.cpp create mode 100644 gps/android/2.0/AGnss.cpp create mode 100644 gps/android/2.0/AGnss.h create mode 100644 gps/android/2.0/AGnssRil.cpp create mode 100644 gps/android/2.0/AGnssRil.h create mode 100644 gps/android/2.0/Android.mk create mode 100644 gps/android/2.0/Gnss.cpp create mode 100644 gps/android/2.0/Gnss.h create mode 100644 gps/android/2.0/GnssBatching.cpp create mode 100644 gps/android/2.0/GnssBatching.h create mode 100644 gps/android/2.0/GnssConfiguration.cpp create mode 100644 gps/android/2.0/GnssConfiguration.h create mode 100644 gps/android/2.0/GnssDebug.cpp create mode 100644 gps/android/2.0/GnssDebug.h create mode 100644 gps/android/2.0/GnssGeofencing.cpp create mode 100644 gps/android/2.0/GnssGeofencing.h create mode 100644 gps/android/2.0/GnssMeasurement.cpp create mode 100644 gps/android/2.0/GnssMeasurement.h create mode 100644 gps/android/2.0/GnssNi.cpp create mode 100644 gps/android/2.0/GnssNi.h create mode 100644 gps/android/2.0/android.hardware.gnss@2.0-service-qti.rc create mode 100644 gps/android/2.0/android.hardware.gnss@2.0-service-qti.xml create mode 100644 gps/android/2.0/location_api/BatchingAPIClient.cpp create mode 100644 gps/android/2.0/location_api/BatchingAPIClient.h create mode 100644 gps/android/2.0/location_api/GeofenceAPIClient.cpp create mode 100644 gps/android/2.0/location_api/GeofenceAPIClient.h create mode 100644 gps/android/2.0/location_api/GnssAPIClient.cpp create mode 100644 gps/android/2.0/location_api/GnssAPIClient.h create mode 100644 gps/android/2.0/location_api/LocationUtil.cpp create mode 100644 gps/android/2.0/location_api/LocationUtil.h create mode 100644 gps/android/2.0/location_api/MeasurementAPIClient.cpp create mode 100644 gps/android/2.0/location_api/MeasurementAPIClient.h create mode 100644 gps/android/2.0/service.cpp delete mode 100644 gps/android/AGnss.cpp delete mode 100644 gps/android/AGnss.h delete mode 100644 gps/android/AGnssRil.cpp delete mode 100644 gps/android/AGnssRil.h delete mode 100644 gps/android/Gnss.cpp delete mode 100644 gps/android/Gnss.h delete mode 100644 gps/android/GnssBatching.cpp delete mode 100644 gps/android/GnssBatching.h delete mode 100644 gps/android/GnssConfiguration.cpp delete mode 100644 gps/android/GnssConfiguration.h delete mode 100644 gps/android/GnssDebug.cpp delete mode 100644 gps/android/GnssDebug.h delete mode 100644 gps/android/GnssGeofencing.cpp delete mode 100644 gps/android/GnssGeofencing.h delete mode 100644 gps/android/GnssMeasurement.cpp delete mode 100644 gps/android/GnssMeasurement.h delete mode 100644 gps/android/GnssNi.cpp delete mode 100644 gps/android/GnssNi.h delete mode 100644 gps/android/android.hardware.gnss@1.0-service-qti.rc delete mode 100644 gps/android/location_api/BatchingAPIClient.cpp delete mode 100644 gps/android/location_api/BatchingAPIClient.h delete mode 100644 gps/android/location_api/GeofenceAPIClient.cpp delete mode 100644 gps/android/location_api/GeofenceAPIClient.h delete mode 100644 gps/android/location_api/GnssAPIClient.cpp delete mode 100644 gps/android/location_api/GnssAPIClient.h delete mode 100644 gps/android/location_api/LocationUtil.cpp delete mode 100644 gps/android/location_api/LocationUtil.h delete mode 100644 gps/android/location_api/MeasurementAPIClient.cpp delete mode 100644 gps/android/location_api/MeasurementAPIClient.h create mode 100644 gps/android/measurement_corrections/1.0/MeasurementCorrections.cpp create mode 100644 gps/android/measurement_corrections/1.0/MeasurementCorrections.h delete mode 100644 gps/android/service.cpp create mode 100644 gps/android/utils/Android.mk create mode 100644 gps/android/utils/battery_listener.cpp create mode 100644 gps/android/utils/battery_listener.h create mode 100644 gps/android/visibility_control/1.0/GnssVisibilityControl.cpp create mode 100644 gps/android/visibility_control/1.0/GnssVisibilityControl.h create mode 100644 gps/batching/Android.mk create mode 100644 gps/batching/BatchingAdapter.cpp create mode 100644 gps/batching/BatchingAdapter.h create mode 100644 gps/batching/location_batching.cpp delete mode 100644 gps/configure.ac create mode 100644 gps/core/EngineHubProxyBase.h create mode 100644 gps/core/LocContext.cpp create mode 100644 gps/core/LocContext.h delete mode 100644 gps/core/LocDualContext.cpp delete mode 100644 gps/core/LocDualContext.h delete mode 100644 gps/core/Makefile.am delete mode 100644 gps/core/UlpProxyBase.h delete mode 100644 gps/core/configure.ac delete mode 100644 gps/core/loc-core.pc.in create mode 100644 gps/etc/flp.conf create mode 100644 gps/etc/gps.conf create mode 100644 gps/etc/izat.conf create mode 100644 gps/etc/lowi.conf create mode 100644 gps/etc/sap.conf create mode 100644 gps/etc/xtwifi.conf create mode 100644 gps/geofence/Android.mk create mode 100644 gps/geofence/GeofenceAdapter.cpp create mode 100644 gps/geofence/GeofenceAdapter.h create mode 100644 gps/geofence/location_geofence.cpp delete mode 100644 gps/gnss/Makefile.am delete mode 100644 gps/gnsspps/Makefile.am delete mode 100644 gps/gnsspps/configure.ac delete mode 100644 gps/gnsspps/gnsspps.pc.in delete mode 100644 gps/loc-hal.pc.in create mode 100644 gps/location/ILocationAPI.h create mode 100644 gps/location/LocationDataTypes.h delete mode 100644 gps/location/Makefile.am delete mode 100644 gps/location/configure.ac delete mode 100644 gps/location/location-api.pc.in delete mode 100644 gps/utils/Makefile.am delete mode 100644 gps/utils/configure.ac delete mode 100644 gps/utils/gps-utils.pc.in create mode 100644 wifi/wifi_legacy_service/1.0-legacy/Android.bp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/THREADING.README create mode 100644 wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc create mode 100644 wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc create mode 100644 wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/service.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp create mode 100644 wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk index d027ba1..4b6aaee 100644 --- a/BoardConfigCommon.mk +++ b/BoardConfigCommon.mk @@ -103,9 +103,8 @@ EXCLUDE_SERIF_FONTS := true TARGET_FS_CONFIG_GEN := $(VENDOR_PATH)/config.fs # GPS -BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := msm8996 -BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET := true -DEVICE_SPECIFIC_GPS_PATH := $(VENDOR_PATH)/gps +BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default +LOC_HIDL_VERSION := 3.0 # HIDL DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE := \ diff --git a/gps/Android.mk b/gps/Android.mk index 23b2a66..f1088a4 100644 --- a/gps/Android.mk +++ b/gps/Android.mk @@ -1,6 +1,5 @@ ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) LOCAL_PATH := $(call my-dir) include $(LOCAL_PATH)/build/target_specific_features.mk - include $(call all-makefiles-under,$(LOCAL_PATH)) endif diff --git a/gps/CleanSpec.mk b/gps/CleanSpec.mk deleted file mode 100644 index dd1849d..0000000 --- a/gps/CleanSpec.mk +++ /dev/null @@ -1,50 +0,0 @@ -# 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 deleted file mode 100644 index cd4a731..0000000 --- a/gps/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -# 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 +#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 AGnss::setCallback(const sp& 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 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 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 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 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(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 +#include +#include + +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 setCallback(const sp& callback) override; + + Return dataConnClosed() override; + + Return dataConnFailed() override; + + Return dataConnOpen(const hidl_string& apn, + IAGnss::ApnIpType apnIpType) override; + + Return 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 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..0437cf1 --- /dev/null +++ b/gps/android/1.0/AGnssRil.cpp @@ -0,0 +1,114 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "Gnss.h" +#include "AGnssRil.h" +#include + +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 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; + + // 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, false, typeout, 0); + } + 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 +#include +#include + +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 setCallback(const sp& /*callback*/) override { + return Void(); + } + Return setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { + return Void(); + } + Return setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { + return false; + } + Return updateNetworkAvailability(bool /*available*/, + const hidl_string& /*apn*/) override { + return false; + } + Return 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..d85e0a4 --- /dev/null +++ b/gps/android/1.0/Gnss.cpp @@ -0,0 +1,360 @@ +/* + * 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_GnssInterface" +#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include "Gnss.h" +#include +#include "battery_listener.h" + +typedef const GnssInterface* (getLocationInterface)(); + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +static sp sGnss; +void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnss != nullptr) { + 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; + // 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) { + delete mApi; + 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) { + LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); + getLocationInterface* getter = NULL; + const char *error = NULL; + dlerror(); + void *handle = dlopen("libgnss.so", RTLD_NOW); + if (NULL == handle || (error = dlerror()) != NULL) { + LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); + } else { + getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); + if ((error = dlerror()) != NULL) { + LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); + getter = NULL; + } + } + + if (NULL == getter) { + getGnssInterfaceFailed = true; + } else { + mGnssInterface = (const GnssInterface*)(*getter)(); + } + } + return mGnssInterface; +} + +Return Gnss::setCallback(const sp& 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 Gnss::setGnssNiCb(const sp& callback) { + ENTRY_LOG_CALLFLOW(); + mGnssNiCbIface = callback; + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); + } + return true; +} + +Return 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.lppProfile = gnssConfig.lppProfile; + } + 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 Gnss::start() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStart(); + } + return retVal; +} + +Return Gnss::stop() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStop(); + } + return retVal; +} + +Return Gnss::cleanup() { + ENTRY_LOG_CALLFLOW(); + + if (mApi != nullptr) { + mApi->gnssDisable(); + } + + return Void(); +} + +Return 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 Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); + return true; + } else { + return false; + } +} + +Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssDeleteAidingData(aidingDataFlags); + } + return Void(); +} + +Return 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> Gnss::getExtensionAGnss() { + ENTRY_LOG_CALLFLOW(); + mAGnssIface = new AGnss(this); + return mAGnssIface; +} + +Return> Gnss::getExtensionGnssNi() { + ENTRY_LOG_CALLFLOW(); + mGnssNi = new GnssNi(this); + return mGnssNi; +} + +Return> Gnss::getExtensionGnssMeasurement() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return> Gnss::getExtensionGnssConfiguration() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return> Gnss::getExtensionGnssGeofencing() { + ENTRY_LOG_CALLFLOW(); + mGnssGeofencingIface = new GnssGeofencing(); + return mGnssGeofencingIface; +} + +Return> Gnss::getExtensionGnssBatching() { + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +Return> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return> 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 setCallback(const sp& callback) override; + Return start() override; + Return stop() override; + Return cleanup() override; + Return injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) override; + Return injectTime(int64_t timeMs, + int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return> getExtensionAGnss() override; + Return> getExtensionGnssNi() override; + Return> getExtensionGnssMeasurement() override; + Return> getExtensionGnssConfiguration() override; + Return> getExtensionGnssGeofencing() override; + Return> getExtensionGnssBatching() override; + + Return> getExtensionAGnssRil() override; + + inline Return> getExtensionGnssNavigationMessage() override { + return nullptr; + } + + inline Return> getExtensionXtra() override { + return nullptr; + } + + Return> getExtensionGnssDebug() override; + + // These methods are not part of the IGnss base class. + GnssAPIClient* getApi(); + Return setGnssNiCb(const sp& niCb); + Return updateConfiguration(GnssConfig& gnssConfig); + const GnssInterface* getGnssInterface(); + + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + + private: + struct GnssDeathRecipient : hidl_death_recipient { + GnssDeathRecipient(sp gnss) : mGnss(gnss) { + } + ~GnssDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnss; + }; + + private: + sp mGnssDeathRecipient = nullptr; + + sp mAGnssIface = nullptr; + sp mGnssNi = nullptr; + sp mGnssMeasurement = nullptr; + sp mGnssConfig = nullptr; + sp mGnssGeofencingIface = nullptr; + sp mGnssBatching = nullptr; + sp mGnssDebug = nullptr; + sp mGnssRil = nullptr; + + GnssAPIClient* mApi = nullptr; + sp mGnssCbIface = nullptr; + sp 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..3e5a9f4 --- /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 +#include +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssBatching::GnssBatchingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssBatching != nullptr) { + mGnssBatching->stop(); + mGnssBatching->cleanup(); + } +} + +GnssBatching::GnssBatching() : mApi(nullptr) { + mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); +} + +GnssBatching::~GnssBatching() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return GnssBatching::init(const sp& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + 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 GnssBatching::getBatchSize() { + uint16_t ret = 0; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->getBatchSize(); + } + return ret; +} + +Return 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 GnssBatching::flush() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->flushBatchedLocations(); + } + return Void(); +} + +Return GnssBatching::stop() { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->stopSession(); + } + return ret; +} + +Return 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 +#include + + +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 init(const sp& callback) override; + Return getBatchSize() override; + Return start(const IGnssBatching::Options& options ) override; + Return flush() override; + Return stop() override; + Return cleanup() override; + + private: + struct GnssBatchingDeathRecipient : hidl_death_recipient { + GnssBatchingDeathRecipient(sp gnssBatching) : + mGnssBatching(gnssBatching) { + } + ~GnssBatchingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssBatching; + }; + + private: + sp mGnssBatchingDeathRecipient = nullptr; + sp 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..0b62249 --- /dev/null +++ b/gps/android/1.0/GnssConfiguration.cpp @@ -0,0 +1,230 @@ +/* + * 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 +#include "Gnss.h" +#include "GnssConfiguration.h" +#include + +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 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 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 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return GnssConfiguration::setLppProfile(uint8_t lppProfile) { + 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_LPP_PROFILE_VALID_BIT; + switch (lppProfile) { + case 0: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; + break; + case 1: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; + break; + case 2: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; + break; + case 3: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; + break; + default: + LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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..1629e06 --- /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 +#include + +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 setSuplVersion(uint32_t version) override; + Return setSuplMode(uint8_t mode) override; + Return setSuplEs(bool enabled) override; + Return setLppProfile(uint8_t lppProfile) override; + Return setGlonassPositioningProtocol(uint8_t protocol) override; + Return setEmergencySuplPdn(bool enable) override; + Return 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 +#include +#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 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 s_array = { }; + + for (uint32_t i=0; i +#include + +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 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..2a8ff88 --- /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 +#include +#include "GnssGeofencing.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssGeofencing != nullptr) { + mGnssGeofencing->removeAllGeofences(); + } +} + +GnssGeofencing::GnssGeofencing() : mApi(nullptr) { + mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); +} + +GnssGeofencing::~GnssGeofencing() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. +Return GnssGeofencing::setCallback(const sp& 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 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(lastTransition), + monitorTransitions, + notificationResponsivenessMs, + unknownTimerMs); + } + return Void(); +} + +Return GnssGeofencing::pauseGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofencePause(geofenceId); + } + return Void(); +} + +Return 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 GnssGeofencing::removeGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceRemove(geofenceId); + } + return Void(); +} + +Return 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 +#include + +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 setCallback(const sp& callback) override; + Return addGeofence(int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) override; + + Return pauseGeofence(int32_t geofenceId) override; + Return resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; + Return 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 removeAllGeofences(); + + private: + struct GnssGeofencingDeathRecipient : hidl_death_recipient { + GnssGeofencingDeathRecipient(sp gnssGeofencing) : + mGnssGeofencing(gnssGeofencing) { + } + ~GnssGeofencingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssGeofencing; + }; + + private: + sp mGnssGeofencingDeathRecipient = nullptr; + sp 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..1c65bd6 --- /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 +#include +#include "GnssMeasurement.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssMeasurement != nullptr) { + mGnssMeasurement->close(); + } +} + +GnssMeasurement::GnssMeasurement() { + mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); + mApi = new MeasurementAPIClient(); +} + +GnssMeasurement::~GnssMeasurement() { + if (mApi) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. + +Return GnssMeasurement::setCallback( + const sp& callback) { + + Return 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 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 +#include +#include + +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 setCallback( + const sp& callback) override; + Return close() override; + + private: + struct GnssMeasurementDeathRecipient : hidl_death_recipient { + GnssMeasurementDeathRecipient(sp gnssMeasurement) : + mGnssMeasurement(gnssMeasurement) { + } + ~GnssMeasurementDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssMeasurement; + }; + + private: + sp mGnssMeasurementDeathRecipient = nullptr; + sp 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 +#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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(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 GnssNi::setCallback(const sp& 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 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 +#include + +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 setCallback(const sp& callback) override; + Return respond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) override; + + private: + struct GnssNiDeathRecipient : hidl_death_recipient { + GnssNiDeathRecipient(sp gnssNi) : mGnssNi(gnssNi) { + } + ~GnssNiDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssNi; + }; + + private: + sp mGnssNiDeathRecipient = nullptr; + sp 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 @@ + + + + android.hardware.gnss + hwbinder + @1.0::IGnss/default + + + 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..264ab83 --- /dev/null +++ b/gps/android/1.0/location_api/BatchingAPIClient.cpp @@ -0,0 +1,196 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAPIClient" + +#include +#include + +#include "LocationUtil.h" +#include "BatchingAPIClient.h" + +#include "limits.h" + + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask); + +BatchingAPIClient::BatchingAPIClient(const sp& callback) : + LocationAPIClientBase(), + mGnssBatchingCbIface(callback), + mDefaultId(UINT_MAX), + mLocationCapabilitiesMask(0) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + if (mGnssBatchingCbIface != nullptr) { + locationCallbacks.batchingCb = [this](size_t count, Location* location, + BatchingOptions batchOptions) { + onBatchingCb(count, location, batchOptions); + }; + } + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +BatchingAPIClient::~BatchingAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +int BatchingAPIClient::getBatchSize() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + return locAPIGetBatchSize(); +} + +int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; +} + +void BatchingAPIClient::onBatchingCb(size_t count, Location* location, + BatchingOptions /*batchOptions*/) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); + if (mGnssBatchingCbIface != nullptr && count > 0) { + hidl_vec locationVec; + locationVec.resize(count); + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i]); + } + auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask) +{ + memset(&out, 0, sizeof(LocationOptions)); + out.size = sizeof(LocationOptions); + out.minInterval = (uint32_t)(in.periodNanos / 1000000L); + out.minDistance = 0; + out.mode = GNSS_SUPL_MODE_STANDALONE; + if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + out.mode = GNSS_SUPL_MODE_MSA; + if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + out.mode = GNSS_SUPL_MODE_MSB; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/BatchingAPIClient.h b/gps/android/1.0/location_api/BatchingAPIClient.h new file mode 100644 index 0000000..5d64df3 --- /dev/null +++ b/gps/android/1.0/location_api/BatchingAPIClient.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef BATCHING_API_CLINET_H +#define BATCHING_API_CLINET_H + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp& callback); + ~BatchingAPIClient(); + 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: + sp mGnssBatchingCbIface; + uint32_t mDefaultId; + LocationCapabilitiesMask mLocationCapabilitiesMask; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // BATCHING_API_CLINET_H diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.cpp b/gps/android/1.0/location_api/GeofenceAPIClient.cpp new file mode 100644 index 0000000..774a049 --- /dev/null +++ b/gps/android/1.0/location_api/GeofenceAPIClient.cpp @@ -0,0 +1,275 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_GeofenceApiClient" + +#include +#include + +#include "LocationUtil.h" +#include "GeofenceAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +GeofenceAPIClient::GeofenceAPIClient(const sp& callback) : + LocationAPIClientBase(), + mGnssGeofencingCbIface(callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + + locationCallbacks.geofenceBreachCb = nullptr; + if (mGnssGeofencingCbIface != nullptr) { + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + onGeofenceBreachCb(geofenceBreachNotification); + }; + + locationCallbacks.geofenceStatusCb = + [this](GeofenceStatusNotification geofenceStatusNotification) { + onGeofenceStatusCb(geofenceStatusNotification); + }; + } + + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) +{ + LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, + geofence_id, latitude, longitude, radius_meters, + last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms); + + GeofenceOption options; + memset(&options, 0, sizeof(GeofenceOption)); + options.size = sizeof(GeofenceOption); + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT; + options.responsiveness = notification_responsiveness_ms; + + GeofenceInfo data; + data.size = sizeof(GeofenceInfo); + data.latitude = latitude; + data.longitude = longitude; + data.radius = radius_meters; + + LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); + if (LOCATION_ERROR_SUCCESS != err) { + onAddGeofencesCb(1, &err, &geofence_id); + } +} + +void GeofenceAPIClient::geofencePause(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIPauseGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); + GeofenceBreachTypeMask mask = 0; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + mask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + mask |= GEOFENCE_BREACH_EXIT_BIT; + locAPIResumeGeofences(1, &geofence_id, &mask); +} + +void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIRemoveGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceRemoveAll() +{ + LOC_LOGD("%s]", __FUNCTION__); + // TODO locAPIRemoveAllGeofences(); +} + +// callbacks +void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < geofenceBreachNotification.count; i++) { + GnssLocation gnssLocation; + convertGnssLocation(geofenceBreachNotification.location, gnssLocation); + + IGnssGeofenceCallback::GeofenceTransition transition; + if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) + transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; + else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) + transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; + else { + // continue with other breach if transition is + // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED + continue; + } + + auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( + geofenceBreachNotification.ids[i], gnssLocation, transition, + static_cast(geofenceBreachNotification.timestamp)); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); + if (mGnssGeofencingCbIface != nullptr) { + IGnssGeofenceCallback::GeofenceAvailability status = + IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; + if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { + status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; + } + GnssLocation gnssLocation; + memset(&gnssLocation, 0, sizeof(GnssLocation)); + auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_EXISTS) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; + auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/GeofenceAPIClient.h b/gps/android/1.0/location_api/GeofenceAPIClient.h new file mode 100644 index 0000000..dc99ddd --- /dev/null +++ b/gps/android/1.0/location_api/GeofenceAPIClient.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GEOFENCE_API_CLINET_H +#define GEOFENCE_API_CLINET_H + + +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp& callback); + virtual ~GeofenceAPIClient() = default; + + 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: + sp mGnssGeofencingCbIface; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GEOFENCE_API_CLINET_H diff --git a/gps/android/1.0/location_api/GnssAPIClient.cpp b/gps/android/1.0/location_api/GnssAPIClient.cpp new file mode 100644 index 0000000..b9fe2b2 --- /dev/null +++ b/gps/android/1.0/location_api/GnssAPIClient.cpp @@ -0,0 +1,566 @@ +/* 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_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include +#include + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnss; +using ::android::hardware::gnss::V1_0::IGnssCallback; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); + +GnssAPIClient::GnssAPIClient(const sp& gpsCb, + const sp& niCb) : + LocationAPIClientBase(), + mGnssCbIface(nullptr), + mGnssNiCbIface(nullptr), + mControlClient(new LocationAPIControlClient()), + mLocationCapabilitiesMask(0), + mLocationCapabilitiesCached(false) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + // set default LocationOptions. + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = 1000; + mTrackingOptions.minDistance = 0; + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + + gnssUpdateCallbacks(gpsCb, niCb); +} + +GnssAPIClient::~GnssAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient) { + delete mControlClient; + mControlClient = nullptr; + } +} + +// for GpsInterface +void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + mMutex.lock(); + mGnssCbIface = gpsCb; + mGnssNiCbIface = niCb; + mMutex.unlock(); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.trackingCb = [this](Location location) { + onTrackingCb(location); + }; + } + + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + + locationCallbacks.gnssNiCb = nullptr; + loc_core::ContextBase* context = + loc_core::LocContext::getLocContext( + NULL, NULL, + loc_core::LocContext::mLocationHalName, false); + 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; + } + mTrackingOptions.minDistance = preferredAccuracyMeters; + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; + data.posEngineMask = STANDARD_POSITIONING_ENGINE; + + if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) + data.deleteAll = true; + else { + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) + data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) + data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) + data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) + data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) + data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) + data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) + data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) + data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) + data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) + data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) + data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) + data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; + } + mControlClient->locAPIGnssDeleteAidingData(data); +} + +void GnssAPIClient::gnssEnable(LocationTechnologyType techType) +{ + LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIEnable(techType); +} + +void GnssAPIClient::gnssDisable() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIDisable(); +} + +void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIGnssUpdateConfig(gnssConfig); +} + +void GnssAPIClient::requestCapabilities() { + // only send capablities if it's already cached, otherwise the first time LocationAPI + // is initialized, capabilities will be sent by LocationAPI + if (mLocationCapabilitiesCached) { + onCapabilitiesCb(mLocationCapabilitiesMask); + } +} + +// callbacks +void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __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; + if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw = 2018; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw = 2017; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw = 2016; + } else { + gnssInfo.yearOfHw = 2015; + } + LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); + auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onTrackingCb(Location location) +{ + LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + GnssLocation gnssLocation; + convertGnssLocation(location, gnssLocation); + auto r = gnssCbIface->gnssLocationCb(gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) +{ + LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); + mMutex.lock(); + auto gnssNiCbIface(mGnssNiCbIface); + mMutex.unlock(); + + if (gnssNiCbIface == nullptr) { + LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); + return; + } + + IGnssNiCallback::GnssNiNotification notificationGnss = {}; + + notificationGnss.notificationId = id; + + if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; + else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; + + if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; + + notificationGnss.timeoutSec = gnssNiNotification.timeout; + + if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || + gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; + + notificationGnss.requestorId = gnssNiNotification.requestor; + + notificationGnss.notificationMessage = gnssNiNotification.message; + + if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + gnssNiCbIface->niNotifyCb(notificationGnss); +} + +void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSvStatus svStatus; + convertGnssSvStatus(gnssSvNotification, svStatus); + auto r = gnssCbIface->gnssSvStatusCb(svStatus); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) +{ + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + const std::string s(gnssNmeaNotification.nmea); + std::stringstream ss(s); + std::string each; + while(std::getline(ss, each, '\n')) { + each += '\n'; + android::hardware::hidl_string nmeaString; + nmeaString.setToExternal(each.c_str(), each.length()); + auto r = gnssCbIface->gnssNmeaCb( + static_cast(gnssNmeaNotification.timestamp), nmeaString); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, + gnssNmeaNotification.nmea, gnssNmeaNotification.length, + r.description().c_str()); + } + } + } +} + +void GnssAPIClient::onStartTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onStopTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) +{ + memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); + out.numSvs = in.count; + if (out.numSvs > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; + info.svid = in.gnssSvs[i].svId; + convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); + info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; + info.elevationDegrees = in.gnssSvs[i].elevation; + info.azimuthDegrees = in.gnssSvs[i].azimuth; + info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; + info.svFlag = static_cast(IGnssCallback::GnssSvFlags::NONE); + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/GnssAPIClient.h b/gps/android/1.0/location_api/GnssAPIClient.h new file mode 100644 index 0000000..4e4b4a9 --- /dev/null +++ b/gps/android/1.0/location_api/GnssAPIClient.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GNSS_API_CLINET_H +#define GNSS_API_CLINET_H + + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp& gpsCb, + const sp& niCb); + virtual ~GnssAPIClient(); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb); + bool gnssStart(); + bool gnssStop(); + bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = 0); + + // for GpsNiInterface + void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse); + + // these apis using LocationAPIControlClient + void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags); + void gnssEnable(LocationTechnologyType techType); + void gnssDisable(); + void gnssConfigurationUpdate(const GnssConfig& gnssConfig); + + inline LocationCapabilitiesMask gnssGetCapabilities() const { + return mLocationCapabilitiesMask; + } + void requestCapabilities(); + + // callbacks we are interested in + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onTrackingCb(Location location) final; + void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final; + void onGnssSvCb(GnssSvNotification gnssSvNotification) final; + void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final; + + void onStartTrackingCb(LocationError error) final; + void onStopTrackingCb(LocationError error) final; + +private: + sp mGnssCbIface; + sp mGnssNiCbIface; + std::mutex mMutex; + LocationAPIControlClient* mControlClient; + LocationCapabilitiesMask mLocationCapabilitiesMask; + bool mLocationCapabilitiesCached; + TrackingOptions mTrackingOptions; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GNSS_API_CLINET_H diff --git a/gps/android/1.0/location_api/LocationUtil.cpp b/gps/android/1.0/location_api/LocationUtil.cpp new file mode 100644 index 0000000..102593b --- /dev/null +++ b/gps/android/1.0/location_api/LocationUtil.cpp @@ -0,0 +1,206 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::V1_0::GnssConstellationType; +using ::android::hardware::gnss::V1_0::GnssLocationFlags; + +void convertGnssLocation(Location& in, GnssLocation& out) +{ + memset(&out, 0, sizeof(GnssLocation)); + if (in.flags & LOCATION_HAS_LAT_LONG_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG; + out.latitudeDegrees = in.latitude; + out.longitudeDegrees = in.longitude; + } + if (in.flags & LOCATION_HAS_ALTITUDE_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE; + out.altitudeMeters = in.altitude; + } + if (in.flags & LOCATION_HAS_SPEED_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED; + out.speedMetersPerSec = in.speed; + } + if (in.flags & LOCATION_HAS_BEARING_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING; + out.bearingDegrees = in.bearing; + } + if (in.flags & LOCATION_HAS_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY; + out.horizontalAccuracyMeters = in.accuracy; + } + if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY; + out.verticalAccuracyMeters = in.verticalAccuracy; + } + if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY; + out.speedAccuracyMetersPerSecond = in.speedAccuracy; + } + if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY; + out.bearingAccuracyDegrees = in.bearingAccuracy; + } + + out.timestamp = static_cast(in.timestamp); +} + +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) { + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) { + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + out.altitude = in.altitudeMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) { + out.flags |= LOCATION_HAS_SPEED_BIT; + out.speed = in.speedMetersPerSec; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + out.flags |= LOCATION_HAS_BEARING_BIT; + out.bearing = in.bearingDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + out.flags |= LOCATION_HAS_ACCURACY_BIT; + out.accuracy = in.horizontalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + out.verticalAccuracy = in.verticalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.bearingAccuracy = in.bearingAccuracyDegrees; + } + + out.timestamp = static_cast(in.timestamp); +} + +void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) +{ + switch(in) { + case GNSS_SV_TYPE_GPS: + out = GnssConstellationType::GPS; + break; + case GNSS_SV_TYPE_SBAS: + out = GnssConstellationType::SBAS; + break; + case GNSS_SV_TYPE_GLONASS: + out = GnssConstellationType::GLONASS; + break; + case GNSS_SV_TYPE_QZSS: + out = GnssConstellationType::QZSS; + break; + case GNSS_SV_TYPE_BEIDOU: + out = GnssConstellationType::BEIDOU; + break; + case GNSS_SV_TYPE_GALILEO: + out = GnssConstellationType::GALILEO; + break; + case GNSS_SV_TYPE_UNKNOWN: + default: + out = GnssConstellationType::UNKNOWN; + break; + } +} + +void 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..9e0cd36 --- /dev/null +++ b/gps/android/1.0/location_api/LocationUtil.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOCATION_UTIL_H +#define LOCATION_UTIL_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void convertGnssLocation(Location& in, V1_0::GnssLocation& out); +void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); +void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); +void 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..73709e3 --- /dev/null +++ b/gps/android/1.0/location_api/MeasurementAPIClient.cpp @@ -0,0 +1,276 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_MeasurementAPIClient" + +#include +#include + +#include "LocationUtil.h" +#include "MeasurementAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssMeasurement; +using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback; + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out); +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out); +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out); + +MeasurementAPIClient::MeasurementAPIClient() : + mGnssMeasurementCbIface(nullptr), + mTracking(false) +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +MeasurementAPIClient::~MeasurementAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +// for GpsInterface +Return +MeasurementAPIClient::measurementSetCallback(const sp& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return +MeasurementAPIClient::startTracking() +{ + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + + locationCallbacks.gnssMeasurementsCb = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + locationCallbacks.gnssMeasurementsCb = + [this](GnssMeasurementsNotification gnssMeasurementsNotification) { + onGnssMeasurementsCb(gnssMeasurementsNotification); + }; + } + + locAPISetCallbacks(locationCallbacks); + + TrackingOptions options = {}; + memset(&options, 0, sizeof(TrackingOptions)); + options.size = sizeof(TrackingOptions); + options.minInterval = 1000; + options.mode = GNSS_SUPL_MODE_STANDALONE; + + mTracking = true; + LOC_LOGD("%s]: start tracking session", __FUNCTION__); + locAPIStartTracking(options); + return IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +// for GpsMeasurementInterface +void MeasurementAPIClient::measurementClose() { + LOC_LOGD("%s]: ()", __FUNCTION__); + mTracking = false; + locAPIStopTracking(); +} + +// callbacks +void MeasurementAPIClient::onGnssMeasurementsCb( + GnssMeasurementsNotification gnssMeasurementsNotification) +{ + LOC_LOGD("%s]: (count: %zu active: %d)", + __FUNCTION__, gnssMeasurementsNotification.count, mTracking); + if (mTracking) { + mMutex.lock(); + sp gnssMeasurementCbIface = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + gnssMeasurementCbIface = mGnssMeasurementCbIface; + } + mMutex.unlock(); + + if (gnssMeasurementCbIface != nullptr) { + V1_0::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from GnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement)); + if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL; + out.svid = in.svId; + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/1.0/location_api/MeasurementAPIClient.h b/gps/android/1.0/location_api/MeasurementAPIClient.h new file mode 100644 index 0000000..c357313 --- /dev/null +++ b/gps/android/1.0/location_api/MeasurementAPIClient.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 MEASUREMENT_API_CLINET_H +#define MEASUREMENT_API_CLINET_H + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + virtual ~MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return measurementSetCallback( + const sp& callback); + void measurementClose(); + Return startTracking(); + + // callbacks we are interested in + void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final; + +private: + std::mutex mMutex; + sp 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 +#include +#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(); + 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 +#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 AGnss::setCallback(const sp& 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 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 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 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 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(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 +#include +#include + +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 setCallback(const sp& callback) override; + + Return dataConnClosed() override; + + Return dataConnFailed() override; + + Return dataConnOpen(const hidl_string& apn, + IAGnss::ApnIpType apnIpType) override; + + Return 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 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..1e774f1 --- /dev/null +++ b/gps/android/1.1/AGnssRil.cpp @@ -0,0 +1,114 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "Gnss.h" +#include "AGnssRil.h" +#include + +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 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; + + // 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, false, typeout, 0); + } + 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 +#include +#include + +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 setCallback(const sp& /*callback*/) override { + return Void(); + } + Return setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { + return Void(); + } + Return setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { + return false; + } + Return updateNetworkAvailability(bool /*available*/, + const hidl_string& /*apn*/) override { + return false; + } + Return 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..bea556f --- /dev/null +++ b/gps/android/1.1/Gnss.cpp @@ -0,0 +1,477 @@ +/* + * 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_GnssInterface" +#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include "Gnss.h" +#include + +#include "battery_listener.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 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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnss != nullptr) { + 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; + // 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) { + delete mApi; + 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) { + LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); + getLocationInterface* getter = NULL; + const char *error = NULL; + dlerror(); + void *handle = dlopen("libgnss.so", RTLD_NOW); + if (NULL == handle || (error = dlerror()) != NULL) { + LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); + } else { + getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); + if ((error = dlerror()) != NULL) { + LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); + getter = NULL; + } + } + + if (NULL == getter) { + getGnssInterfaceFailed = true; + } else { + mGnssInterface = (const GnssInterface*)(*getter)(); + } + } + return mGnssInterface; +} + +Return Gnss::setCallback(const sp& 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 Gnss::setGnssNiCb(const sp& callback) { + ENTRY_LOG_CALLFLOW(); + mGnssNiCbIface = callback; + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); + } + return true; +} + +Return 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.lppProfile = gnssConfig.lppProfile; + } + 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 Gnss::start() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStart(); + } + return retVal; +} + +Return Gnss::stop() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStop(); + } + return retVal; +} + +Return Gnss::cleanup() { + ENTRY_LOG_CALLFLOW(); + + if (mApi != nullptr) { + mApi->gnssDisable(); + } + + return Void(); +} + +Return 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 Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); + return true; + } else { + return false; + } +} + +Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssDeleteAidingData(aidingDataFlags); + } + return Void(); +} + +Return 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> Gnss::getExtensionAGnss() { + ENTRY_LOG_CALLFLOW(); + mAGnssIface = new AGnss(this); + return mAGnssIface; +} + +Return> Gnss::getExtensionGnssNi() { + ENTRY_LOG_CALLFLOW(); + mGnssNi = new GnssNi(this); + return mGnssNi; +} + +Return> Gnss::getExtensionGnssMeasurement() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return> Gnss::getExtensionGnssConfiguration() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return> Gnss::getExtensionGnssGeofencing() { + ENTRY_LOG_CALLFLOW(); + mGnssGeofencingIface = new GnssGeofencing(); + return mGnssGeofencingIface; +} + +Return> Gnss::getExtensionGnssBatching() { + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +Return> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return> Gnss::getExtensionAGnssRil() { + mGnssRil = new AGnssRil(this); + return mGnssRil; +} + +// Methods from ::android::hardware::gnss::V1_1::IGnss follow. +Return Gnss::setCallback_1_1(const sp& 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); + } + return setCallback(callback); +} + +Return 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> Gnss::getExtensionGnssMeasurement_1_1() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return> Gnss::getExtensionGnssConfiguration_1_1() { + ENTRY_LOG_CALLFLOW(); + if (mGnssConfig == nullptr) + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return 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 (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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 setCallback(const sp& callback) override; + Return start() override; + Return stop() override; + Return cleanup() override; + Return injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) override; + Return injectTime(int64_t timeMs, + int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return> getExtensionAGnss() override; + Return> getExtensionGnssNi() override; + Return> getExtensionGnssMeasurement() override; + Return> getExtensionGnssConfiguration() override; + Return> getExtensionGnssGeofencing() override; + Return> getExtensionGnssBatching() override; + + Return> getExtensionAGnssRil() override; + + inline Return> getExtensionGnssNavigationMessage() override { + return nullptr; + } + + inline Return> getExtensionXtra() override { + return nullptr; + } + + Return> getExtensionGnssDebug() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnss follow. + Return setCallback_1_1(const sp& callback) override; + Return 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> getExtensionGnssMeasurement_1_1() override; + Return> getExtensionGnssConfiguration_1_1() override; + Return injectBestLocation(const GnssLocation& location) override; + + // These methods are not part of the IGnss base class. + GnssAPIClient* getApi(); + Return setGnssNiCb(const sp& niCb); + Return updateConfiguration(GnssConfig& gnssConfig); + const GnssInterface* getGnssInterface(); + + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + + private: + struct GnssDeathRecipient : hidl_death_recipient { + GnssDeathRecipient(sp gnss) : mGnss(gnss) { + } + ~GnssDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnss; + }; + + private: + sp mGnssDeathRecipient = nullptr; + + sp mAGnssIface = nullptr; + sp mGnssNi = nullptr; + sp mGnssMeasurement = nullptr; + sp mGnssConfig = nullptr; + sp mGnssGeofencingIface = nullptr; + sp mGnssBatching = nullptr; + sp mGnssDebug = nullptr; + sp mGnssRil = nullptr; + + GnssAPIClient* mApi = nullptr; + sp mGnssCbIface = nullptr; + sp mGnssCbIface_1_1 = nullptr; + sp 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..9701aff --- /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 +#include +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +void GnssBatching::GnssBatchingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssBatching != nullptr) { + mGnssBatching->stop(); + mGnssBatching->cleanup(); + } +} + +GnssBatching::GnssBatching() : mApi(nullptr) { + mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); +} + +GnssBatching::~GnssBatching() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return GnssBatching::init(const sp& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + 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 GnssBatching::getBatchSize() { + uint16_t ret = 0; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->getBatchSize(); + } + return ret; +} + +Return 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 GnssBatching::flush() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->flushBatchedLocations(); + } + return Void(); +} + +Return GnssBatching::stop() { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->stopSession(); + } + return ret; +} + +Return 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 +#include + + +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 init(const sp& callback) override; + Return getBatchSize() override; + Return start(const IGnssBatching::Options& options ) override; + Return flush() override; + Return stop() override; + Return cleanup() override; + + private: + struct GnssBatchingDeathRecipient : hidl_death_recipient { + GnssBatchingDeathRecipient(sp gnssBatching) : + mGnssBatching(gnssBatching) { + } + ~GnssBatchingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssBatching; + }; + + private: + sp mGnssBatchingDeathRecipient = nullptr; + sp 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..93f9645 --- /dev/null +++ b/gps/android/1.1/GnssConfiguration.cpp @@ -0,0 +1,313 @@ +/* + * 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 +#include "Gnss.h" +#include "GnssConfiguration.h" +#include + +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 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 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 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return GnssConfiguration::setLppProfile(uint8_t lppProfile) { + 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_LPP_PROFILE_VALID_BIT; + switch (lppProfile) { + case 0: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; + break; + case 1: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; + break; + case 2: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; + break; + case 3: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; + break; + default: + LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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 GnssConfiguration::setBlacklist( + const hidl_vec& 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..96681b6 --- /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 +#include + +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 setSuplVersion(uint32_t version) override; + Return setSuplMode(uint8_t mode) override; + Return setSuplEs(bool enabled) override; + Return setLppProfile(uint8_t lppProfile) override; + Return setGlonassPositioningProtocol(uint8_t protocol) override; + Return setEmergencySuplPdn(bool enable) override; + Return setGpsLock(uint8_t lock) override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. + Return setBlacklist( + const hidl_vec& 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 +#include +#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 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 s_array = { }; + + for (uint32_t i=0; i +#include + +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 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..d57a666 --- /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 +#include +#include "GnssGeofencing.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssGeofencing != nullptr) { + mGnssGeofencing->removeAllGeofences(); + } +} + +GnssGeofencing::GnssGeofencing() : mApi(nullptr) { + mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); +} + +GnssGeofencing::~GnssGeofencing() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. +Return GnssGeofencing::setCallback(const sp& 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 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(lastTransition), + monitorTransitions, + notificationResponsivenessMs, + unknownTimerMs); + } + return Void(); +} + +Return GnssGeofencing::pauseGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofencePause(geofenceId); + } + return Void(); +} + +Return 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 GnssGeofencing::removeGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceRemove(geofenceId); + } + return Void(); +} + +Return 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 +#include + +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 setCallback(const sp& callback) override; + Return addGeofence(int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) override; + + Return pauseGeofence(int32_t geofenceId) override; + Return resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; + Return 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 removeAllGeofences(); + + private: + struct GnssGeofencingDeathRecipient : hidl_death_recipient { + GnssGeofencingDeathRecipient(sp gnssGeofencing) : + mGnssGeofencing(gnssGeofencing) { + } + ~GnssGeofencingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssGeofencing; + }; + + private: + sp mGnssGeofencingDeathRecipient = nullptr; + sp 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..ffe5c52 --- /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 +#include +#include "GnssMeasurement.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssMeasurement != nullptr) { + mGnssMeasurement->close(); + } +} + +GnssMeasurement::GnssMeasurement() { + mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); + mApi = new MeasurementAPIClient(); +} + +GnssMeasurement::~GnssMeasurement() { + if (mApi) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. + +Return GnssMeasurement::setCallback( + const sp& callback) { + + Return 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 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::setCallback_1_1( + const sp& callback, bool enableFullTracking) { + + Return 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 +#include +#include + +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 setCallback( + const sp& callback) override; + Return close() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow. + Return setCallback_1_1( + const sp& callback, + bool enableFullTracking) override; + + private: + struct GnssMeasurementDeathRecipient : hidl_death_recipient { + GnssMeasurementDeathRecipient(sp gnssMeasurement) : + mGnssMeasurement(gnssMeasurement) { + } + ~GnssMeasurementDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssMeasurement; + }; + + private: + sp mGnssMeasurementDeathRecipient = nullptr; + sp mGnssMeasurementCbIface = nullptr; + sp 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 +#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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(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 GnssNi::setCallback(const sp& 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 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 +#include + +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 setCallback(const sp& callback) override; + Return respond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) override; + + private: + struct GnssNiDeathRecipient : hidl_death_recipient { + GnssNiDeathRecipient(sp gnssNi) : mGnssNi(gnssNi) { + } + ~GnssNiDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssNi; + }; + + private: + sp mGnssNiDeathRecipient = nullptr; + sp 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 @@ + + + + android.hardware.gnss + hwbinder + @1.1::IGnss/default + + + 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..82a803f --- /dev/null +++ b/gps/android/1.1/location_api/BatchingAPIClient.cpp @@ -0,0 +1,196 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAPIClient" + +#include +#include + +#include "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& callback) : + LocationAPIClientBase(), + mGnssBatchingCbIface(callback), + mDefaultId(UINT_MAX), + mLocationCapabilitiesMask(0) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + if (mGnssBatchingCbIface != nullptr) { + locationCallbacks.batchingCb = [this](size_t count, Location* location, + BatchingOptions batchOptions) { + onBatchingCb(count, location, batchOptions); + }; + } + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +BatchingAPIClient::~BatchingAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +int BatchingAPIClient::getBatchSize() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + return locAPIGetBatchSize(); +} + +int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; +} + +void BatchingAPIClient::onBatchingCb(size_t count, Location* location, + BatchingOptions /*batchOptions*/) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); + if (mGnssBatchingCbIface != nullptr && count > 0) { + hidl_vec locationVec; + locationVec.resize(count); + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i]); + } + auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask) +{ + memset(&out, 0, sizeof(LocationOptions)); + out.size = sizeof(LocationOptions); + out.minInterval = (uint32_t)(in.periodNanos / 1000000L); + out.minDistance = 0; + out.mode = GNSS_SUPL_MODE_STANDALONE; + if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + out.mode = GNSS_SUPL_MODE_MSA; + if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + out.mode = GNSS_SUPL_MODE_MSB; +} + +} // namespace implementation +} // namespace V1_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..64d47a0 --- /dev/null +++ b/gps/android/1.1/location_api/BatchingAPIClient.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef BATCHING_API_CLINET_H +#define BATCHING_API_CLINET_H + +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp& callback); + ~BatchingAPIClient(); + 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: + sp 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 +#include + +#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& callback) : + LocationAPIClientBase(), + mGnssGeofencingCbIface(callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + + locationCallbacks.geofenceBreachCb = nullptr; + if (mGnssGeofencingCbIface != nullptr) { + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + onGeofenceBreachCb(geofenceBreachNotification); + }; + + locationCallbacks.geofenceStatusCb = + [this](GeofenceStatusNotification geofenceStatusNotification) { + onGeofenceStatusCb(geofenceStatusNotification); + }; + } + + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) +{ + LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, + geofence_id, latitude, longitude, radius_meters, + last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms); + + GeofenceOption options; + memset(&options, 0, sizeof(GeofenceOption)); + options.size = sizeof(GeofenceOption); + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT; + options.responsiveness = notification_responsiveness_ms; + + GeofenceInfo data; + data.size = sizeof(GeofenceInfo); + data.latitude = latitude; + data.longitude = longitude; + data.radius = radius_meters; + + LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); + if (LOCATION_ERROR_SUCCESS != err) { + onAddGeofencesCb(1, &err, &geofence_id); + } +} + +void GeofenceAPIClient::geofencePause(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIPauseGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); + GeofenceBreachTypeMask mask = 0; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + mask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + mask |= GEOFENCE_BREACH_EXIT_BIT; + locAPIResumeGeofences(1, &geofence_id, &mask); +} + +void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIRemoveGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceRemoveAll() +{ + LOC_LOGD("%s]", __FUNCTION__); + // TODO locAPIRemoveAllGeofences(); +} + +// callbacks +void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < geofenceBreachNotification.count; i++) { + GnssLocation gnssLocation; + convertGnssLocation(geofenceBreachNotification.location, gnssLocation); + + IGnssGeofenceCallback::GeofenceTransition transition; + if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) + transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; + else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) + transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; + else { + // continue with other breach if transition is + // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED + continue; + } + + auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( + geofenceBreachNotification.ids[i], gnssLocation, transition, + static_cast(geofenceBreachNotification.timestamp)); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); + if (mGnssGeofencingCbIface != nullptr) { + IGnssGeofenceCallback::GeofenceAvailability status = + IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; + if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { + status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; + } + GnssLocation gnssLocation; + memset(&gnssLocation, 0, sizeof(GnssLocation)); + auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_EXISTS) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; + auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +} // namespace implementation +} // namespace V1_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..c74a59a --- /dev/null +++ b/gps/android/1.1/location_api/GeofenceAPIClient.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GEOFENCE_API_CLINET_H +#define GEOFENCE_API_CLINET_H + + +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp& callback); + virtual ~GeofenceAPIClient() = default; + + 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: + sp 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..9a95fdf --- /dev/null +++ b/gps/android/1.1/location_api/GnssAPIClient.cpp @@ -0,0 +1,566 @@ +/* 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_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include +#include + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include + +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& gpsCb, + const sp& niCb) : + LocationAPIClientBase(), + mGnssCbIface(nullptr), + mGnssNiCbIface(nullptr), + mControlClient(new LocationAPIControlClient()), + mLocationCapabilitiesMask(0), + mLocationCapabilitiesCached(false) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + // set default LocationOptions. + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = 1000; + mTrackingOptions.minDistance = 0; + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + + gnssUpdateCallbacks(gpsCb, niCb); +} + +GnssAPIClient::~GnssAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient) { + delete mControlClient; + mControlClient = nullptr; + } +} + +// for GpsInterface +void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + mMutex.lock(); + mGnssCbIface = gpsCb; + mGnssNiCbIface = niCb; + mMutex.unlock(); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.trackingCb = [this](Location location) { + onTrackingCb(location); + }; + } + + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + + locationCallbacks.gnssNiCb = nullptr; + loc_core::ContextBase* context = + loc_core::LocContext::getLocContext( + NULL, NULL, + loc_core::LocContext::mLocationHalName, false); + 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; + } + mTrackingOptions.minDistance = preferredAccuracyMeters; + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; + data.posEngineMask = STANDARD_POSITIONING_ENGINE; + + if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) + data.deleteAll = true; + else { + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) + data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) + data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) + data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) + data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) + data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) + data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) + data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) + data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) + data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) + data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) + data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) + data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; + } + mControlClient->locAPIGnssDeleteAidingData(data); +} + +void GnssAPIClient::gnssEnable(LocationTechnologyType techType) +{ + LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIEnable(techType); +} + +void GnssAPIClient::gnssDisable() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIDisable(); +} + +void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIGnssUpdateConfig(gnssConfig); +} + +void GnssAPIClient::requestCapabilities() { + // only send capablities if it's already cached, otherwise the first time LocationAPI + // is initialized, capabilities will be sent by LocationAPI + if (mLocationCapabilitiesCached) { + onCapabilitiesCb(mLocationCapabilitiesMask); + } +} + +// callbacks +void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __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; + if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw = 2018; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw = 2017; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw = 2016; + } else { + gnssInfo.yearOfHw = 2015; + } + LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); + auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onTrackingCb(Location location) +{ + LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + GnssLocation gnssLocation; + convertGnssLocation(location, gnssLocation); + auto r = gnssCbIface->gnssLocationCb(gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) +{ + LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); + mMutex.lock(); + auto gnssNiCbIface(mGnssNiCbIface); + mMutex.unlock(); + + if (gnssNiCbIface == nullptr) { + LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); + return; + } + + IGnssNiCallback::GnssNiNotification notificationGnss = {}; + + notificationGnss.notificationId = id; + + if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; + else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; + + if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; + + notificationGnss.timeoutSec = gnssNiNotification.timeout; + + if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || + gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; + + notificationGnss.requestorId = gnssNiNotification.requestor; + + notificationGnss.notificationMessage = gnssNiNotification.message; + + if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + gnssNiCbIface->niNotifyCb(notificationGnss); +} + +void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSvStatus svStatus; + convertGnssSvStatus(gnssSvNotification, svStatus); + auto r = gnssCbIface->gnssSvStatusCb(svStatus); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) +{ + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + const std::string s(gnssNmeaNotification.nmea); + std::stringstream ss(s); + std::string each; + while(std::getline(ss, each, '\n')) { + each += '\n'; + android::hardware::hidl_string nmeaString; + nmeaString.setToExternal(each.c_str(), each.length()); + auto r = gnssCbIface->gnssNmeaCb( + static_cast(gnssNmeaNotification.timestamp), nmeaString); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, + gnssNmeaNotification.nmea, gnssNmeaNotification.length, + r.description().c_str()); + } + } + } +} + +void GnssAPIClient::onStartTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onStopTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) +{ + memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); + out.numSvs = in.count; + if (out.numSvs > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; + info.svid = in.gnssSvs[i].svId; + convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); + info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; + info.elevationDegrees = in.gnssSvs[i].elevation; + info.azimuthDegrees = in.gnssSvs[i].azimuth; + info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; + info.svFlag = static_cast(IGnssCallback::GnssSvFlags::NONE); + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; + } +} + +} // namespace implementation +} // namespace V1_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..82f8fbf --- /dev/null +++ b/gps/android/1.1/location_api/GnssAPIClient.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GNSS_API_CLINET_H +#define GNSS_API_CLINET_H + + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp& gpsCb, + const sp& niCb); + virtual ~GnssAPIClient(); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb); + bool gnssStart(); + bool gnssStop(); + bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = 0); + + // for GpsNiInterface + void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse); + + // these apis using LocationAPIControlClient + void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags); + void gnssEnable(LocationTechnologyType techType); + void gnssDisable(); + void gnssConfigurationUpdate(const GnssConfig& gnssConfig); + + inline LocationCapabilitiesMask gnssGetCapabilities() const { + return mLocationCapabilitiesMask; + } + void requestCapabilities(); + + // callbacks we are interested in + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onTrackingCb(Location location) final; + void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final; + void onGnssSvCb(GnssSvNotification gnssSvNotification) final; + void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final; + + void onStartTrackingCb(LocationError error) final; + void onStopTrackingCb(LocationError error) final; + +private: + sp mGnssCbIface; + sp 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..f1d051c --- /dev/null +++ b/gps/android/1.1/location_api/LocationUtil.cpp @@ -0,0 +1,206 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_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(in.timestamp); +} + +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) { + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) { + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + out.altitude = in.altitudeMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) { + out.flags |= LOCATION_HAS_SPEED_BIT; + out.speed = in.speedMetersPerSec; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + out.flags |= LOCATION_HAS_BEARING_BIT; + out.bearing = in.bearingDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + out.flags |= LOCATION_HAS_ACCURACY_BIT; + out.accuracy = in.horizontalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + out.verticalAccuracy = in.verticalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.bearingAccuracy = in.bearingAccuracyDegrees; + } + + out.timestamp = static_cast(in.timestamp); +} + +void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) +{ + switch(in) { + case GNSS_SV_TYPE_GPS: + out = GnssConstellationType::GPS; + break; + case GNSS_SV_TYPE_SBAS: + out = GnssConstellationType::SBAS; + break; + case GNSS_SV_TYPE_GLONASS: + out = GnssConstellationType::GLONASS; + break; + case GNSS_SV_TYPE_QZSS: + out = GnssConstellationType::QZSS; + break; + case GNSS_SV_TYPE_BEIDOU: + out = GnssConstellationType::BEIDOU; + break; + case GNSS_SV_TYPE_GALILEO: + out = GnssConstellationType::GALILEO; + break; + case GNSS_SV_TYPE_UNKNOWN: + default: + out = GnssConstellationType::UNKNOWN; + break; + } +} + +void 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..63f4f6f --- /dev/null +++ b/gps/android/1.1/location_api/LocationUtil.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOCATION_UTIL_H +#define LOCATION_UTIL_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_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 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..6f25067 --- /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 +#include + +#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 +MeasurementAPIClient::measurementSetCallback(const sp& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return +MeasurementAPIClient::measurementSetCallback_1_1( + const sp& 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 +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 gnssMeasurementCbIface = nullptr; + sp 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; + out.svid = in.svId; + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +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..38811c5 --- /dev/null +++ b/gps/android/1.1/location_api/MeasurementAPIClient.h @@ -0,0 +1,84 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MEASUREMENT_API_CLINET_H +#define MEASUREMENT_API_CLINET_H + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_1 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + virtual ~MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return measurementSetCallback( + const sp& callback); + Return measurementSetCallback_1_1( + const sp& callback, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + void measurementClose(); + Return 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: + std::mutex mMutex; + sp mGnssMeasurementCbIface; + sp 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 +#include +#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(); + 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 +#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 AGnss::setCallback(const sp& 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 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 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 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 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(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 +#include +#include + +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 setCallback(const sp& callback) override; + + Return dataConnClosed() override; + + Return dataConnFailed() override; + + Return dataConnOpen(uint64_t networkHandle, const hidl_string& apn, + V2_0::IAGnss::ApnIpType apnIpType) override; + + Return 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 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..a477fc2 --- /dev/null +++ b/gps/android/2.0/AGnssRil.cpp @@ -0,0 +1,133 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "Gnss.h" +#include "AGnssRil.h" +#include + +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 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; + + // 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, false, typeout, 0); + } + return true; +} +Return AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) { + ENTRY_LOG_CALLFLOW(); + + 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; + } + mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected, + typeout, roaming, (NetworkHandle) attributes.networkHandle); + } + 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 +#include +#include + +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 setCallback(const sp& /*callback*/) override { + return Void(); + } + Return setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { + return Void(); + } + Return setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { + return false; + } + Return updateNetworkAvailability(bool /*available*/, + const hidl_string& /*apn*/) override { + return false; + } + Return updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override; + + // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow + Return 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..b6790c5 --- /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 \ + ../measurement_corrections/1.0/MeasurementCorrections.cpp \ + ../visibility_control/1.0/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_PATH)/../measurement_corrections/1.0 \ + $(LOCAL_PATH)/../visibility_control/1.0 +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.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..af76b72 --- /dev/null +++ b/gps/android/2.0/Gnss.cpp @@ -0,0 +1,671 @@ +/* + * 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_GnssInterface" +#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include "Gnss.h" +#include "LocationUtil.h" +#include "battery_listener.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 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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnss != nullptr) { + 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; + // 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) { + delete mApi; + 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) { + LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); + getLocationInterface* getter = NULL; + const char *error = NULL; + dlerror(); + void *handle = dlopen("libgnss.so", RTLD_NOW); + if (NULL == handle || (error = dlerror()) != NULL) { + LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); + } else { + getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); + if ((error = dlerror()) != NULL) { + LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); + getter = NULL; + } + } + + if (NULL == getter) { + getGnssInterfaceFailed = true; + } else { + mGnssInterface = (const GnssInterface*)(*getter)(); + } + } + return mGnssInterface; +} + +Return Gnss::setCallback(const sp& 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 Gnss::setGnssNiCb(const sp& callback) { + ENTRY_LOG_CALLFLOW(); + mGnssNiCbIface = callback; + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); + } + return true; +} + +Return 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.lppProfile = gnssConfig.lppProfile; + } + 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 Gnss::start() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStart(); + } + return retVal; +} + +Return Gnss::stop() { + ENTRY_LOG_CALLFLOW(); + bool retVal = false; + GnssAPIClient* api = getApi(); + if (api) { + retVal = api->gnssStop(); + } + return retVal; +} + +Return Gnss::cleanup() { + ENTRY_LOG_CALLFLOW(); + + if (mApi != nullptr) { + mApi->gnssStop(); + mApi->gnssDisable(); + } + + return Void(); +} + +Return 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 Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) { + ENTRY_LOG_CALLFLOW(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); + return true; + } else { + return false; + } +} + +Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssDeleteAidingData(aidingDataFlags); + } + return Void(); +} + +Return 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> Gnss::getExtensionAGnss() { + ENTRY_LOG_CALLFLOW(); + // deprecated function. Must return nullptr to pass VTS + return nullptr; +} + +Return> Gnss::getExtensionGnssNi() { + ENTRY_LOG_CALLFLOW(); + // deprecated function. Must return nullptr to pass VTS + return nullptr; +} + +Return> Gnss::getExtensionGnssMeasurement() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return> Gnss::getExtensionGnssConfiguration() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return> Gnss::getExtensionGnssGeofencing() { + ENTRY_LOG_CALLFLOW(); + mGnssGeofencingIface = new GnssGeofencing(); + return mGnssGeofencingIface; +} + +Return> Gnss::getExtensionGnssBatching() { + ENTRY_LOG_CALLFLOW(); + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +Return> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return> Gnss::getExtensionAGnssRil() { + ENTRY_LOG_CALLFLOW(); + mGnssRil = new AGnssRil(this); + return mGnssRil; +} + +// Methods from ::android::hardware::gnss::V1_1::IGnss follow. +Return Gnss::setCallback_1_1(const sp& 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); + } + + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface); + api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS); + api->requestCapabilities(); + } + + return true; +} + +Return 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> 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> Gnss::getExtensionGnssConfiguration_1_1() { + ENTRY_LOG_CALLFLOW(); + if (mGnssConfig == nullptr) + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return 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 (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 Gnss::setCallback_2_0(const sp& 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); + } + + GnssAPIClient* api = getApi(); + if (api != nullptr) { + api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0); + api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS); + api->requestCapabilities(); + } + + return true; +} + +Return> Gnss::getExtensionAGnss_2_0() { + ENTRY_LOG_CALLFLOW(); + mAGnssIface_2_0 = new AGnss(this); + return mAGnssIface_2_0; +} +Return> Gnss::getExtensionAGnssRil_2_0() { + mGnssRil = new AGnssRil(this); + return mGnssRil; +} + +Return> Gnss::getExtensionGnssConfiguration_2_0() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} +Return> 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> + Gnss::getExtensionMeasurementCorrections() { + // We do not support, so return nullptr to pass VTS + return nullptr; +} +Return> + Gnss::getExtensionVisibilityControl() { + ENTRY_LOG_CALLFLOW(); + if (mVisibCtrl == nullptr) { + mVisibCtrl = new GnssVisibilityControl(this); + } + return mVisibCtrl; +} + +Return 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> Gnss::getExtensionGnssDebug_2_0() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return> Gnss::getExtensionGnssBatching_2_0() { + ENTRY_LOG_CALLFLOW(); + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 setCallback(const sp& callback) override; + Return start() override; + Return stop() override; + Return cleanup() override; + Return injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) override; + Return injectTime(int64_t timeMs, + int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return> getExtensionAGnss() override; + Return> getExtensionGnssNi() override; + Return> getExtensionGnssMeasurement() override; + Return> getExtensionGnssConfiguration() override; + Return> getExtensionGnssGeofencing() override; + Return> getExtensionGnssBatching() override; + + Return> getExtensionAGnssRil() override; + + inline Return> getExtensionGnssNavigationMessage() override { + return nullptr; + } + + inline Return> getExtensionXtra() override { + return nullptr; + } + + Return> getExtensionGnssDebug() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnss follow. + Return setCallback_1_1(const sp& callback) override; + Return 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> getExtensionGnssMeasurement_1_1() override; + Return> getExtensionGnssConfiguration_1_1() override; + Return injectBestLocation(const GnssLocation& location) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnss follow. + Return setCallback_2_0(const sp& callback) override; + Return> getExtensionAGnss_2_0() override; + Return> getExtensionAGnssRil_2_0() override; + + Return> getExtensionGnssConfiguration_2_0() override; + Return> + getExtensionMeasurementCorrections() override; + Return> getExtensionGnssMeasurement_2_0() override; + + Return injectBestLocation_2_0(const ::android::hardware::gnss::V2_0::GnssLocation& location) override; + + Return> getExtensionGnssBatching_2_0() override; + Return> getExtensionGnssDebug_2_0() override; + + + /** + * This method returns the IGnssVisibilityControl interface. + * + * @return visibilityControlIface Handle to the IGnssVisibilityControl interface. + */ + Return> + getExtensionVisibilityControl() override; + + + // These methods are not part of the IGnss base class. + GnssAPIClient* getApi(); + Return setGnssNiCb(const sp& niCb); + Return updateConfiguration(GnssConfig& gnssConfig); + const GnssInterface* getGnssInterface(); + + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + + private: + struct GnssDeathRecipient : hidl_death_recipient { + GnssDeathRecipient(sp gnss) : mGnss(gnss) { + } + ~GnssDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnss; + }; + + private: + sp mGnssDeathRecipient = nullptr; + + sp mGnssNi = nullptr; + sp mGnssGeofencingIface = nullptr; + sp mAGnssIface = nullptr; + sp mGnssCbIface = nullptr; + sp mGnssNiCbIface = nullptr; + sp mGnssCbIface_1_1 = nullptr; + sp mAGnssIface_2_0 = nullptr; + sp mGnssRil = nullptr; + sp mGnssMeasurement = nullptr; + sp mGnssConfig = nullptr; + sp mGnssBatching = nullptr; + sp mGnssDebug = nullptr; + sp mGnssCbIface_2_0 = nullptr; + sp mGnssMeasCorr = nullptr; + sp 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..7a937fc --- /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 +#include +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssBatching::GnssBatchingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssBatching != nullptr) { + mGnssBatching->stop(); + mGnssBatching->cleanup(); + } +} + +GnssBatching::GnssBatching() : mApi(nullptr) { + mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); +} + +GnssBatching::~GnssBatching() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return GnssBatching::init(const sp& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + 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 GnssBatching::getBatchSize() { + uint16_t ret = 0; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->getBatchSize(); + } + return ret; +} + +Return 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 GnssBatching::flush() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->flushBatchedLocations(); + } + return Void(); +} + +Return GnssBatching::stop() { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->stopSession(); + } + return ret; +} + +Return 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 GnssBatching::init_2_0(const sp& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + 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 +#include + + +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 init(const sp& callback) override; + Return getBatchSize() override; + Return start(const IGnssBatching::Options& options ) override; + Return flush() override; + Return stop() override; + Return cleanup() override; + + // Methods from ::android::hardware::gnss::V2_0::IGnssBatching follow. + Return init_2_0(const sp& callback) override; + + private: + struct GnssBatchingDeathRecipient : hidl_death_recipient { + GnssBatchingDeathRecipient(sp gnssBatching) : + mGnssBatching(gnssBatching) { + } + ~GnssBatchingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssBatching; + }; + + private: + sp mGnssBatchingDeathRecipient = nullptr; + sp mGnssBatchingCbIface = nullptr; + BatchingAPIClient* mApi = nullptr; + sp 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..363d2b1 --- /dev/null +++ b/gps/android/2.0/GnssConfiguration.cpp @@ -0,0 +1,321 @@ +/* + * 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 +#include "Gnss.h" +#include "GnssConfiguration.h" +#include "ContextBase.h" +#include + +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 GnssConfiguration::setSuplEs(bool enabled) { + // deprecated function. Must return false to pass VTS + return false; +} + +Return 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 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return GnssConfiguration::setLppProfile(uint8_t lppProfile) { + 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; + switch (lppProfile) { + case 0: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; + break; + case 1: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; + break; + case 2: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; + break; + case 3: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; + break; + default: + LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return 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 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; + break; + } + + mGnss->updateConfiguration(config); + // Must return false to pass VTS + return false; +} + +Return 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 GnssConfiguration::setBlacklist( + const hidl_vec& 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 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..202a9fd --- /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 +#include + +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 setSuplVersion(uint32_t version) override; + Return setSuplMode(uint8_t mode) override; + Return setSuplEs(bool enabled) override; + Return setLppProfile(uint8_t lppProfile) override; + Return setGlonassPositioningProtocol(uint8_t protocol) override; + Return setEmergencySuplPdn(bool enable) override; + Return setGpsLock(uint8_t lock) override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. + Return setBlacklist( + const hidl_vec& blacklist) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow. + Return 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 +#include +#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 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 s_array; + + for (uint32_t i=0; i 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 s_array; + + for (uint32_t i=0; i +#include + +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 getDebugData(getDebugData_cb _hidl_cb) override; + // Methods from ::android::hardware::gnss::V2_0::IGnssDebug follow. + Return 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..b72d835 --- /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 +#include +#include "GnssGeofencing.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied( + uint64_t cookie, const wp& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssGeofencing != nullptr) { + mGnssGeofencing->removeAllGeofences(); + } +} + +GnssGeofencing::GnssGeofencing() : mApi(nullptr) { + mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); +} + +GnssGeofencing::~GnssGeofencing() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. +Return GnssGeofencing::setCallback(const sp& 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 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(lastTransition), + monitorTransitions, + notificationResponsivenessMs, + unknownTimerMs); + } + return Void(); +} + +Return GnssGeofencing::pauseGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofencePause(geofenceId); + } + return Void(); +} + +Return 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 GnssGeofencing::removeGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceRemove(geofenceId); + } + return Void(); +} + +Return 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 +#include + +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 setCallback(const sp& callback) override; + Return addGeofence(int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) override; + + Return pauseGeofence(int32_t geofenceId) override; + Return resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; + Return 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 removeAllGeofences(); + + private: + struct GnssGeofencingDeathRecipient : hidl_death_recipient { + GnssGeofencingDeathRecipient(sp gnssGeofencing) : + mGnssGeofencing(gnssGeofencing) { + } + ~GnssGeofencingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssGeofencing; + }; + + private: + sp mGnssGeofencingDeathRecipient = nullptr; + sp 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..721a48c --- /dev/null +++ b/gps/android/2.0/GnssMeasurement.cpp @@ -0,0 +1,165 @@ +/* + * 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 +#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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(cookie), &who); + if (mGnssMeasurement != nullptr) { + mGnssMeasurement->close(); + } +} + +GnssMeasurement::GnssMeasurement() { + mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); + mApi = new MeasurementAPIClient(); +} + +GnssMeasurement::~GnssMeasurement() { + if (mApi) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. +Return GnssMeasurement::setCallback( + const sp& callback) { + + Return 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 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; + } + if (mGnssMeasurementCbIface_2_0 != nullptr) { + mGnssMeasurementCbIface_2_0->unlinkToDeath(mGnssMeasurementDeathRecipient); + mGnssMeasurementCbIface_2_0 = nullptr; + } + mApi->measurementClose(); + + return Void(); +} + +// Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow. +Return GnssMeasurement::setCallback_1_1( + const sp& callback, bool enableFullTracking) { + + Return 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); +} +// Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow. +Return GnssMeasurement::setCallback_2_0( + const sp& callback, + bool enableFullTracking) { + + Return 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; + } + + 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..000b00f --- /dev/null +++ b/gps/android/2.0/GnssMeasurement.h @@ -0,0 +1,86 @@ +/* + * 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 +#include +#include + +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 setCallback( + const sp& callback) override; + Return close() override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssMeasurement follow. + Return setCallback_1_1( + const sp& callback, + bool enableFullTracking) override; + + // Methods from ::android::hardware::gnss::V2_0::IGnssMeasurement follow. + Return setCallback_2_0( + const sp& callback, + bool enableFullTracking) override; + private: + struct GnssMeasurementDeathRecipient : hidl_death_recipient { + GnssMeasurementDeathRecipient(sp gnssMeasurement) : + mGnssMeasurement(gnssMeasurement) { + } + ~GnssMeasurementDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssMeasurement; + }; + + private: + sp mGnssMeasurementDeathRecipient = nullptr; + sp mGnssMeasurementCbIface = nullptr; + sp mGnssMeasurementCbIface_1_1 = nullptr; + sp mGnssMeasurementCbIface_2_0 = nullptr; + MeasurementAPIClient* mApi; +}; + +} // 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 +#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& who) { + LOC_LOGE("%s] service died. cookie: %llu, who: %p", + __FUNCTION__, static_cast(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 GnssNi::setCallback(const sp& 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 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 +#include + +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 setCallback(const sp& callback) override; + Return respond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) override; + + private: + struct GnssNiDeathRecipient : hidl_death_recipient { + GnssNiDeathRecipient(sp gnssNi) : mGnssNi(gnssNi) { + } + ~GnssNiDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp& who) override; + sp mGnssNi; + }; + + private: + sp mGnssNiDeathRecipient = nullptr; + sp 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/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 @@ + + + + android.hardware.gnss + hwbinder + @1.1::IGnss/default + @2.0::IGnss/default + + + 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..49cd18a --- /dev/null +++ b/gps/android/2.0/location_api/BatchingAPIClient.cpp @@ -0,0 +1,250 @@ +/* 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 +#include + +#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& 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& 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& callback) +{ + mMutex.lock(); + mGnssBatchingCbIface = callback; + mMutex.unlock(); + + if (mGnssBatchingCbIface != nullptr) { + setCallbacks(); + } +} + +void BatchingAPIClient::gnssUpdateCallbacks_2_0(const sp& 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(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast(opts.periodNanos), static_cast(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __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 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 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..7198341 --- /dev/null +++ b/gps/android/2.0/location_api/BatchingAPIClient.h @@ -0,0 +1,81 @@ +/* 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 +#include +#include +#include + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp& callback); + BatchingAPIClient(const sp& callback); + void gnssUpdateCallbacks(const sp& callback); + void gnssUpdateCallbacks_2_0(const sp& callback); + ~BatchingAPIClient(); + 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(); + std::mutex mMutex; + sp mGnssBatchingCbIface; + uint32_t mDefaultId; + LocationCapabilitiesMask mLocationCapabilitiesMask; + sp 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 +#include + +#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& 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(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..71049de --- /dev/null +++ b/gps/android/2.0/location_api/GeofenceAPIClient.h @@ -0,0 +1,76 @@ +/* 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 +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp& callback); + virtual ~GeofenceAPIClient() = default; + + 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: + sp 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..a3cdd27 --- /dev/null +++ b/gps/android/2.0/location_api/GnssAPIClient.cpp @@ -0,0 +1,728 @@ +/* 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_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include +#include + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include + +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& out); + +GnssAPIClient::GnssAPIClient(const sp& gpsCb, + const sp& 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& 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( + NULL, NULL, + loc_core::LocContext::mLocationHalName, false); + 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& gpsCb, + const sp& 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& 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; + } + mTrackingOptions.minDistance = preferredAccuracyMeters; + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT | + 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]: (%02x)", __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; + if (capabilitiesMask & LOCATION_CAPABILITIES_PRIVACY_BIT) { + gnssInfo.yearOfHw = 2019; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw = 2018; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw = 2017; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw = 2016; + } else { + gnssInfo.yearOfHw = 2015; + } + 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 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(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(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(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + out.gnssSvList[i].svid = in.gnssSvs[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(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& out) +{ + out.resize(in.count); + for (size_t i = 0; i < in.count; i++) { + out[i].v1_0.svid = in.gnssSvs[i].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(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..63b4561 --- /dev/null +++ b/gps/android/2.0/location_api/GnssAPIClient.h @@ -0,0 +1,114 @@ +/* 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 +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp& gpsCb, + const sp& niCb); + GnssAPIClient(const sp& gpsCb); + virtual ~GnssAPIClient(); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp& gpsCb, + const sp& niCb); + void gnssUpdateCallbacks_2_0(const sp& 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: + void setCallbacks(); + void initLocationOptions(); + sp mGnssCbIface; + sp mGnssNiCbIface; + std::mutex mMutex; + LocationAPIControlClient* mControlClient; + LocationCapabilitiesMask mLocationCapabilitiesMask; + bool mLocationCapabilitiesCached; + TrackingOptions mTrackingOptions; + bool mTracking; + sp 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..8a30066 --- /dev/null +++ b/gps/android/2.0/location_api/LocationUtil.cpp @@ -0,0 +1,311 @@ +/* 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 +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::gnss::V2_0::GnssLocation; +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(in.timestamp); +} + +void convertGnssLocation(Location& in, V2_0::GnssLocation& out) +{ + memset(&out, 0, sizeof(V2_0::GnssLocation)); + convertGnssLocation(in, out.v1_0); + + struct timespec sinceBootTime; + struct timespec currentTime; + struct timespec sinceBootTimeTest; + int64_t sinceBootTimeNanos = 0; + 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, ¤tTime) != 0) { + break; + } + if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { + break; + }; + sinceBootTimeNanos = sinceBootTime.tv_sec*1000000000 + sinceBootTime.tv_nsec; + int64_t sinceBootTimeTestNanos = + 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("%s]: Delta:%" PRIi64 "ns time too large, retry number #%u...", + __FUNCTION__, sinceBootTimeDeltaNanos, i+1); + } + } + + if (clockGetTimeSuccess) { + int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec; + int64_t locationTimeNanos = in.timestamp*1000000; + LOC_LOGD("%s]: sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" + " locationTimeNanos:%" PRIi64 "", + __FUNCTION__, sinceBootTimeNanos, currentTimeNanos, locationTimeNanos); + if (currentTimeNanos >= locationTimeNanos) { + int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos; + LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos); + if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) { + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + // time uncertainty is 1 ms since it is calculated from utc time that is in ms + out.elapsedRealtime.timeUncertaintyNs = 1000000; + LOC_LOGD("%s]: timestampNs:%" PRIi64 ")", + __FUNCTION__, out.elapsedRealtime.timestampNs); + } + } + } else { + LOC_LOGE("%s]: Failed to calculate elapsedRealtimeNanos timestamp after %u tries", + __FUNCTION__, MAX_GET_TIME_COUNT); + } +} + +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(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 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..8426de7 --- /dev/null +++ b/gps/android/2.0/location_api/LocationUtil.h @@ -0,0 +1,58 @@ +/* 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 +#include +#include + +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 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..dc972ec --- /dev/null +++ b/gps/android/2.0/location_api/MeasurementAPIClient.cpp @@ -0,0 +1,474 @@ +/* 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_MeasurementAPIClient" + +#include +#include + +#include "LocationUtil.h" +#include "MeasurementAPIClient.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); + +MeasurementAPIClient::MeasurementAPIClient() : + mGnssMeasurementCbIface(nullptr), + mGnssMeasurementCbIface_1_1(nullptr), + mGnssMeasurementCbIface_2_0(nullptr), + mTracking(false) +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +MeasurementAPIClient::~MeasurementAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +// for GpsInterface +Return +MeasurementAPIClient::measurementSetCallback(const sp& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return +MeasurementAPIClient::measurementSetCallback_1_1( + const sp& 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 +MeasurementAPIClient::measurementSetCallback_2_0( + const sp& callback, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)", + __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement); + + mMutex.lock(); + mGnssMeasurementCbIface_2_0 = callback; + mMutex.unlock(); + + return startTracking(powerMode, timeBetweenMeasurement); +} + +Return +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 gnssMeasurementCbIface = nullptr; + sp gnssMeasurementCbIface_1_1 = nullptr; + sp 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; + out.svid = in.svId; + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +static void convertGnssData_1_1(GnssMeasurementsNotification& in, + V1_1::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); +} + +static void convertGnssData_2_0(GnssMeasurementsNotification& in, + V2_0::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_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); +} + +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..4146a13 --- /dev/null +++ b/gps/android/2.0/location_api/MeasurementAPIClient.h @@ -0,0 +1,89 @@ +/* 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 +#include +//#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V2_0 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + virtual ~MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return measurementSetCallback( + const sp& callback); + Return measurementSetCallback_1_1( + const sp& callback, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + Return measurementSetCallback_2_0( + const sp& callback, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS); + void measurementClose(); + Return 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: + std::mutex mMutex; + sp mGnssMeasurementCbIface; + sp mGnssMeasurementCbIface_1_1; + sp mGnssMeasurementCbIface_2_0; + + bool mTracking; +}; + +} // 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..664c661 --- /dev/null +++ b/gps/android/2.0/service.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 "android.hardware.gnss@2.0-service-qti" + +#include +#include +#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(); + 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 2.0 service: %d", status); + } + + return 0; +} diff --git a/gps/android/AGnss.cpp b/gps/android/AGnss.cpp deleted file mode 100644 index faaf75e..0000000 --- a/gps/android/AGnss.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 -#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 AGnss::setCallback(const sp& 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.cbPriority = AGPS_CB_PRIORITY_LOW; - - mGnss->getGnssInterface()->agpsInit(cbInfo); - return Void(); -} - -Return 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 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 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 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(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/AGnss.h b/gps/android/AGnss.h deleted file mode 100644 index cdd5931..0000000 --- a/gps/android/AGnss.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 -#include -#include - -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 setCallback(const sp& callback) override; - - Return dataConnClosed() override; - - Return dataConnFailed() override; - - Return dataConnOpen(const hidl_string& apn, - IAGnss::ApnIpType apnIpType) override; - - Return 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 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/AGnssRil.cpp b/gps/android/AGnssRil.cpp deleted file mode 100644 index f4b9849..0000000 --- a/gps/android/AGnssRil.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include "Gnss.h" -#include "AGnssRil.h" -#include - -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 AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) { - ENTRY_LOG_CALLFLOW(); - - // 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: - typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; - break; - } - mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout); - } - return true; -} - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gps/android/AGnssRil.h b/gps/android/AGnssRil.h deleted file mode 100644 index 7f18c57..0000000 --- a/gps/android/AGnssRil.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 -#include -#include - -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 setCallback(const sp& /*callback*/) override { - return Void(); - } - Return setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { - return Void(); - } - Return setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { - return false; - } - Return updateNetworkAvailability(bool /*available*/, - const hidl_string& /*apn*/) override { - return false; - } - Return 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/Android.mk b/gps/android/Android.mk index 8ec95bf..3b5c01f 100644 --- a/gps/android/Android.mk +++ b/gps/android/Android.mk @@ -1,87 +1,15 @@ LOCAL_PATH := $(call my-dir) - +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti -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 - -LOCAL_SHARED_LIBRARIES := \ - liblog \ - libhidlbase \ - libcutils \ - libutils \ - android.hardware.gnss@1.0 \ - -LOCAL_SHARED_LIBRARIES += \ - libloc_core \ - libgps.utils \ - libdl \ - liblocation_api \ - -LOCAL_CFLAGS += $(GNSS_CFLAGS) -include $(BUILD_SHARED_LIBRARY) - -BUILD_GNSS_HIDL_SERVICE := true -ifneq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET), true) -ifneq ($(LW_FEATURE_SET),true) -BUILD_GNSS_HIDL_SERVICE := false -endif # LW_FEATURE_SET -endif # BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET - -ifeq ($(BUILD_GNSS_HIDL_SERVICE), true) -include $(CLEAR_VARS) -LOCAL_MODULE := android.hardware.gnss@1.0-service-qti -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 \ - -LOCAL_SHARED_LIBRARIES += \ - libhidlbase \ - android.hardware.gnss@1.0 \ - -LOCAL_CFLAGS += $(GNSS_CFLAGS) -include $(BUILD_EXECUTABLE) -endif # BUILD_GNSS_HIDL_SERVICE +DIR_LIST := $(LOCAL_PATH) +include $(DIR_LIST)/utils/Android.mk +ifeq ($(GNSS_HIDL_VERSION),2.0) +include $(DIR_LIST)/2.0/Android.mk +else +ifeq ($(GNSS_HIDL_VERSION),1.1) +include $(DIR_LIST)/1.1/Android.mk +else +include $(DIR_LIST)/1.0/Android.mk +endif #GNSS HIDL 1.1 +endif #GNSS HIDL 2.0 +endif #BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/gps/android/Gnss.cpp b/gps/android/Gnss.cpp deleted file mode 100644 index c844118..0000000 --- a/gps/android/Gnss.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - * 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_GnssInterface" - -#include -#include -#include -#include -#include "Gnss.h" -#include - -typedef void* (getLocationInterface)(); - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp& who) { - LOC_LOGE("%s] service died. cookie: %llu, who: %p", - __FUNCTION__, static_cast(cookie), &who); - if (mGnss != nullptr) { - mGnss->stop(); - mGnss->cleanup(); - } -} - -Gnss::Gnss() { - ENTRY_LOG_CALLFLOW(); - // clear pending GnssConfig - memset(&mPendingConfig, 0, sizeof(GnssConfig)); - - mGnssDeathRecipient = new GnssDeathRecipient(this); -} - -Gnss::~Gnss() { - ENTRY_LOG_CALLFLOW(); - if (mApi != nullptr) { - delete mApi; - mApi = 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; -} - -GnssInterface* Gnss::getGnssInterface() { - static bool getGnssInterfaceFailed = false; - if (nullptr == mGnssInterface && !getGnssInterfaceFailed) { - LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); - getLocationInterface* getter = NULL; - const char *error = NULL; - dlerror(); - void *handle = dlopen("libgnss.so", RTLD_NOW); - if (NULL == handle || (error = dlerror()) != NULL) { - LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); - } else { - getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); - if ((error = dlerror()) != NULL) { - LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); - getter = NULL; - } - } - - if (NULL == getter) { - getGnssInterfaceFailed = true; - } else { - mGnssInterface = (GnssInterface*)(*getter)(); - } - } - return mGnssInterface; -} - -Return Gnss::setCallback(const sp& 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 Gnss::setGnssNiCb(const sp& callback) { - ENTRY_LOG_CALLFLOW(); - mGnssNiCbIface = callback; - GnssAPIClient* api = getApi(); - if (api != nullptr) { - api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); - } - return true; -} - -Return 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.lppProfile = gnssConfig.lppProfile; - } - 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; - } - } - return true; -} - -Return Gnss::start() { - ENTRY_LOG_CALLFLOW(); - bool retVal = false; - GnssAPIClient* api = getApi(); - if (api) { - retVal = api->gnssStart(); - } - return retVal; -} - -Return Gnss::stop() { - ENTRY_LOG_CALLFLOW(); - bool retVal = false; - GnssAPIClient* api = getApi(); - if (api) { - retVal = api->gnssStop(); - } - return retVal; -} - -Return Gnss::cleanup() { - ENTRY_LOG_CALLFLOW(); - - if (mApi != nullptr) { - mApi->gnssDisable(); - } - - return Void(); -} - -Return Gnss::injectLocation(double latitudeDegrees, - double longitudeDegrees, - float accuracyMeters) { - ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); - if (nullptr != gnssInterface) { - gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters); - return true; - } else { - return false; - } -} - -Return Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, - int32_t uncertaintyMs) { - ENTRY_LOG_CALLFLOW(); - GnssInterface* gnssInterface = getGnssInterface(); - if (nullptr != gnssInterface) { - gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); - return true; - } else { - return false; - } -} - -Return Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { - ENTRY_LOG_CALLFLOW(); - GnssAPIClient* api = getApi(); - if (api) { - api->gnssDeleteAidingData(aidingDataFlags); - } - return Void(); -} - -Return 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> Gnss::getExtensionAGnss() { - ENTRY_LOG_CALLFLOW(); - mAGnssIface = new AGnss(this); - return mAGnssIface; -} - -Return> Gnss::getExtensionGnssNi() { - ENTRY_LOG_CALLFLOW(); - mGnssNi = new GnssNi(this); - return mGnssNi; -} - -Return> Gnss::getExtensionGnssMeasurement() { - ENTRY_LOG_CALLFLOW(); - if (mGnssMeasurement == nullptr) - mGnssMeasurement = new GnssMeasurement(); - return mGnssMeasurement; -} - -Return> Gnss::getExtensionGnssConfiguration() { - ENTRY_LOG_CALLFLOW(); - mGnssConfig = new GnssConfiguration(this); - return mGnssConfig; -} - -Return> Gnss::getExtensionGnssGeofencing() { - ENTRY_LOG_CALLFLOW(); - mGnssGeofencingIface = new GnssGeofencing(); - return mGnssGeofencingIface; -} - -Return> Gnss::getExtensionGnssBatching() { - mGnssBatching = new GnssBatching(); - return mGnssBatching; -} - -Return> Gnss::getExtensionGnssDebug() { - ENTRY_LOG_CALLFLOW(); - mGnssDebug = new GnssDebug(this); - return mGnssDebug; -} - -Return> 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/Gnss.h b/gps/android/Gnss.h deleted file mode 100644 index 03ef170..0000000 --- a/gps/android/Gnss.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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_0_GNSS_H -#define ANDROID_HARDWARE_GNSS_V1_0_GNSS_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -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 setCallback(const sp& callback) override; - Return start() override; - Return stop() override; - Return cleanup() override; - Return injectLocation(double latitudeDegrees, - double longitudeDegrees, - float accuracyMeters) override; - Return injectTime(int64_t timeMs, - int64_t timeReferenceMs, - int32_t uncertaintyMs) override; - Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; - Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, - V1_0::IGnss::GnssPositionRecurrence recurrence, - uint32_t minIntervalMs, - uint32_t preferredAccuracyMeters, - uint32_t preferredTimeMs) override; - Return> getExtensionAGnss() override; - Return> getExtensionGnssNi() override; - Return> getExtensionGnssMeasurement() override; - Return> getExtensionGnssConfiguration() override; - Return> getExtensionGnssGeofencing() override; - Return> getExtensionGnssBatching() override; - - Return> getExtensionAGnssRil() override; - - inline Return> getExtensionGnssNavigationMessage() override { - return nullptr; - } - - inline Return> getExtensionXtra() override { - return nullptr; - } - - Return> getExtensionGnssDebug() override; - - // These methods are not part of the IGnss base class. - GnssAPIClient* getApi(); - Return setGnssNiCb(const sp& niCb); - Return updateConfiguration(GnssConfig& gnssConfig); - GnssInterface* getGnssInterface(); - - // Callback for ODCPI request - void odcpiRequestCb(const OdcpiRequestInfo& request); - - private: - struct GnssDeathRecipient : hidl_death_recipient { - GnssDeathRecipient(sp gnss) : mGnss(gnss) { - } - ~GnssDeathRecipient() = default; - virtual void serviceDied(uint64_t cookie, const wp& who) override; - sp mGnss; - }; - - private: - sp mGnssDeathRecipient = nullptr; - - sp mAGnssIface = nullptr; - sp mGnssNi = nullptr; - sp mGnssMeasurement = nullptr; - sp mGnssConfig = nullptr; - sp mGnssGeofencingIface = nullptr; - sp mGnssBatching = nullptr; - sp mGnssDebug = nullptr; - sp mGnssRil = nullptr; - - GnssAPIClient* mApi = nullptr; - sp mGnssCbIface = nullptr; - sp mGnssNiCbIface = nullptr; - GnssConfig mPendingConfig; - 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/GnssBatching.cpp b/gps/android/GnssBatching.cpp deleted file mode 100644 index 3e5a9f4..0000000 --- a/gps/android/GnssBatching.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 -#include -#include "GnssBatching.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -void GnssBatching::GnssBatchingDeathRecipient::serviceDied( - uint64_t cookie, const wp& who) { - LOC_LOGE("%s] service died. cookie: %llu, who: %p", - __FUNCTION__, static_cast(cookie), &who); - if (mGnssBatching != nullptr) { - mGnssBatching->stop(); - mGnssBatching->cleanup(); - } -} - -GnssBatching::GnssBatching() : mApi(nullptr) { - mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); -} - -GnssBatching::~GnssBatching() { - if (mApi != nullptr) { - delete mApi; - mApi = nullptr; - } -} - - -// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. -Return GnssBatching::init(const sp& callback) { - if (mApi != nullptr) { - LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); - delete mApi; - 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 GnssBatching::getBatchSize() { - uint16_t ret = 0; - if (mApi == nullptr) { - LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); - } else { - ret = mApi->getBatchSize(); - } - return ret; -} - -Return 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 GnssBatching::flush() { - if (mApi == nullptr) { - LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); - } else { - mApi->flushBatchedLocations(); - } - return Void(); -} - -Return GnssBatching::stop() { - bool ret = false; - if (mApi == nullptr) { - LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); - } else { - ret = mApi->stopSession(); - } - return ret; -} - -Return 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/GnssBatching.h b/gps/android/GnssBatching.h deleted file mode 100644 index 8fab857..0000000 --- a/gps/android/GnssBatching.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 -#include - - -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 init(const sp& callback) override; - Return getBatchSize() override; - Return start(const IGnssBatching::Options& options ) override; - Return flush() override; - Return stop() override; - Return cleanup() override; - - private: - struct GnssBatchingDeathRecipient : hidl_death_recipient { - GnssBatchingDeathRecipient(sp gnssBatching) : - mGnssBatching(gnssBatching) { - } - ~GnssBatchingDeathRecipient() = default; - virtual void serviceDied(uint64_t cookie, const wp& who) override; - sp mGnssBatching; - }; - - private: - sp mGnssBatchingDeathRecipient = nullptr; - sp 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/GnssConfiguration.cpp b/gps/android/GnssConfiguration.cpp deleted file mode 100644 index 15153dd..0000000 --- a/gps/android/GnssConfiguration.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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 -#include "Gnss.h" -#include "GnssConfiguration.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) { -} - -// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow. -Return 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 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 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; - break; - } - - return mGnss->updateConfiguration(config); -} - -Return 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; - break; - } - - return mGnss->updateConfiguration(config); -} - -Return GnssConfiguration::setLppProfile(uint8_t lppProfile) { - 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_LPP_PROFILE_VALID_BIT; - switch (lppProfile) { - case 0: - config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; - break; - case 1: - config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; - break; - case 2: - config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; - break; - case 3: - config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; - break; - default: - LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); - return false; - break; - } - - return mGnss->updateConfiguration(config); -} - -Return 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 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; - break; - } - - return mGnss->updateConfiguration(config); -} - -Return 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/GnssConfiguration.h b/gps/android/GnssConfiguration.h deleted file mode 100644 index 1629e06..0000000 --- a/gps/android/GnssConfiguration.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 -#include - -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 setSuplVersion(uint32_t version) override; - Return setSuplMode(uint8_t mode) override; - Return setSuplEs(bool enabled) override; - Return setLppProfile(uint8_t lppProfile) override; - Return setGlonassPositioningProtocol(uint8_t protocol) override; - Return setEmergencySuplPdn(bool enable) override; - Return 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/GnssDebug.cpp b/gps/android/GnssDebug.cpp deleted file mode 100644 index 3d8e055..0000000 --- a/gps/android/GnssDebug.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 -#include -#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 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; - } - - 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 s_array = { }; - - for (uint32_t i=0; i -#include - -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 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/GnssGeofencing.cpp b/gps/android/GnssGeofencing.cpp deleted file mode 100644 index 2a8ff88..0000000 --- a/gps/android/GnssGeofencing.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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 -#include -#include "GnssGeofencing.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -void GnssGeofencing::GnssGeofencingDeathRecipient::serviceDied( - uint64_t cookie, const wp& who) { - LOC_LOGE("%s] service died. cookie: %llu, who: %p", - __FUNCTION__, static_cast(cookie), &who); - if (mGnssGeofencing != nullptr) { - mGnssGeofencing->removeAllGeofences(); - } -} - -GnssGeofencing::GnssGeofencing() : mApi(nullptr) { - mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); -} - -GnssGeofencing::~GnssGeofencing() { - if (mApi != nullptr) { - delete mApi; - mApi = nullptr; - } -} - -// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. -Return GnssGeofencing::setCallback(const sp& 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 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(lastTransition), - monitorTransitions, - notificationResponsivenessMs, - unknownTimerMs); - } - return Void(); -} - -Return GnssGeofencing::pauseGeofence(int32_t geofenceId) { - if (mApi == nullptr) { - LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); - } else { - mApi->geofencePause(geofenceId); - } - return Void(); -} - -Return 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 GnssGeofencing::removeGeofence(int32_t geofenceId) { - if (mApi == nullptr) { - LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); - } else { - mApi->geofenceRemove(geofenceId); - } - return Void(); -} - -Return 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/GnssGeofencing.h b/gps/android/GnssGeofencing.h deleted file mode 100644 index db5f9d2..0000000 --- a/gps/android/GnssGeofencing.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 -#include - -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 setCallback(const sp& callback) override; - Return addGeofence(int32_t geofenceId, - double latitudeDegrees, - double longitudeDegrees, - double radiusMeters, - IGnssGeofenceCallback::GeofenceTransition lastTransition, - int32_t monitorTransitions, - uint32_t notificationResponsivenessMs, - uint32_t unknownTimerMs) override; - - Return pauseGeofence(int32_t geofenceId) override; - Return resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; - Return 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 removeAllGeofences(); - - private: - struct GnssGeofencingDeathRecipient : hidl_death_recipient { - GnssGeofencingDeathRecipient(sp gnssGeofencing) : - mGnssGeofencing(gnssGeofencing) { - } - ~GnssGeofencingDeathRecipient() = default; - virtual void serviceDied(uint64_t cookie, const wp& who) override; - sp mGnssGeofencing; - }; - - private: - sp mGnssGeofencingDeathRecipient = nullptr; - sp 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/GnssMeasurement.cpp b/gps/android/GnssMeasurement.cpp deleted file mode 100644 index 1c65bd6..0000000 --- a/gps/android/GnssMeasurement.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 -#include -#include "GnssMeasurement.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -void GnssMeasurement::GnssMeasurementDeathRecipient::serviceDied( - uint64_t cookie, const wp& who) { - LOC_LOGE("%s] service died. cookie: %llu, who: %p", - __FUNCTION__, static_cast(cookie), &who); - if (mGnssMeasurement != nullptr) { - mGnssMeasurement->close(); - } -} - -GnssMeasurement::GnssMeasurement() { - mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); - mApi = new MeasurementAPIClient(); -} - -GnssMeasurement::~GnssMeasurement() { - if (mApi) { - delete mApi; - mApi = nullptr; - } -} - -// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. - -Return GnssMeasurement::setCallback( - const sp& callback) { - - Return 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 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/GnssMeasurement.h b/gps/android/GnssMeasurement.h deleted file mode 100644 index 4247dbf..0000000 --- a/gps/android/GnssMeasurement.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 -#include -#include - -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 setCallback( - const sp& callback) override; - Return close() override; - - private: - struct GnssMeasurementDeathRecipient : hidl_death_recipient { - GnssMeasurementDeathRecipient(sp gnssMeasurement) : - mGnssMeasurement(gnssMeasurement) { - } - ~GnssMeasurementDeathRecipient() = default; - virtual void serviceDied(uint64_t cookie, const wp& who) override; - sp mGnssMeasurement; - }; - - private: - sp mGnssMeasurementDeathRecipient = nullptr; - sp 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/GnssNi.cpp b/gps/android/GnssNi.cpp deleted file mode 100644 index d06cc20..0000000 --- a/gps/android/GnssNi.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 -#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& who) { - LOC_LOGE("%s] service died. cookie: %llu, who: %p", - __FUNCTION__, static_cast(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 GnssNi::setCallback(const sp& 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 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/GnssNi.h b/gps/android/GnssNi.h deleted file mode 100644 index 90f62d5..0000000 --- a/gps/android/GnssNi.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 -#include - -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 setCallback(const sp& callback) override; - Return respond(int32_t notifId, - IGnssNiCallback::GnssUserResponseType userResponse) override; - - private: - struct GnssNiDeathRecipient : hidl_death_recipient { - GnssNiDeathRecipient(sp gnssNi) : mGnssNi(gnssNi) { - } - ~GnssNiDeathRecipient() = default; - virtual void serviceDied(uint64_t cookie, const wp& who) override; - sp mGnssNi; - }; - - private: - sp mGnssNiDeathRecipient = nullptr; - sp 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/android.hardware.gnss@1.0-service-qti.rc b/gps/android/android.hardware.gnss@1.0-service-qti.rc deleted file mode 100644 index b5da6f9..0000000 --- a/gps/android/android.hardware.gnss@1.0-service-qti.rc +++ /dev/null @@ -1,4 +0,0 @@ -service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-qti - class hal - user gps - group system gps radio diff --git a/gps/android/location_api/BatchingAPIClient.cpp b/gps/android/location_api/BatchingAPIClient.cpp deleted file mode 100644 index 264ab83..0000000 --- a/gps/android/location_api/BatchingAPIClient.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define LOG_NDEBUG 0 -#define LOG_TAG "LocSvc_BatchingAPIClient" - -#include -#include - -#include "LocationUtil.h" -#include "BatchingAPIClient.h" - -#include "limits.h" - - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::hardware::gnss::V1_0::IGnssBatching; -using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; -using ::android::hardware::gnss::V1_0::GnssLocation; - -static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, - LocationCapabilitiesMask mask); - -BatchingAPIClient::BatchingAPIClient(const sp& callback) : - LocationAPIClientBase(), - mGnssBatchingCbIface(callback), - mDefaultId(UINT_MAX), - mLocationCapabilitiesMask(0) -{ - LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); - - LocationCallbacks locationCallbacks; - memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); - locationCallbacks.size = sizeof(LocationCallbacks); - - locationCallbacks.trackingCb = nullptr; - locationCallbacks.batchingCb = nullptr; - if (mGnssBatchingCbIface != nullptr) { - locationCallbacks.batchingCb = [this](size_t count, Location* location, - BatchingOptions batchOptions) { - onBatchingCb(count, location, batchOptions); - }; - } - locationCallbacks.geofenceBreachCb = nullptr; - locationCallbacks.geofenceStatusCb = nullptr; - locationCallbacks.gnssLocationInfoCb = nullptr; - locationCallbacks.gnssNiCb = nullptr; - locationCallbacks.gnssSvCb = nullptr; - locationCallbacks.gnssNmeaCb = nullptr; - locationCallbacks.gnssMeasurementsCb = nullptr; - - locAPISetCallbacks(locationCallbacks); -} - -BatchingAPIClient::~BatchingAPIClient() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); -} - -int BatchingAPIClient::getBatchSize() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); - return locAPIGetBatchSize(); -} - -int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) -{ - LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, - static_cast(opts.periodNanos), static_cast(opts.flags)); - int retVal = -1; - LocationOptions options; - convertBatchOption(opts, options, mLocationCapabilitiesMask); - uint32_t mode = 0; - if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { - mode = SESSION_MODE_ON_FULL; - } - if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { - retVal = 1; - } - return retVal; -} - -int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) -{ - LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, - static_cast(opts.periodNanos), static_cast(opts.flags)); - int retVal = -1; - LocationOptions options; - convertBatchOption(opts, options, mLocationCapabilitiesMask); - - uint32_t mode = 0; - if (opts.flags == static_cast(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { - mode = SESSION_MODE_ON_FULL; - } - if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { - retVal = 1; - } - return retVal; -} - -int BatchingAPIClient::stopSession() -{ - LOC_LOGD("%s]: ", __FUNCTION__); - int retVal = -1; - if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { - retVal = 1; - } - return retVal; -} - -void BatchingAPIClient::getBatchedLocation(int last_n_locations) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); - locAPIGetBatchedLocations(mDefaultId, last_n_locations); -} - -void BatchingAPIClient::flushBatchedLocations() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); - locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); -} - -void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) -{ - LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); - mLocationCapabilitiesMask = capabilitiesMask; -} - -void BatchingAPIClient::onBatchingCb(size_t count, Location* location, - BatchingOptions /*batchOptions*/) -{ - LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); - if (mGnssBatchingCbIface != nullptr && count > 0) { - hidl_vec locationVec; - locationVec.resize(count); - for (size_t i = 0; i < count; i++) { - convertGnssLocation(location[i], locationVec[i]); - } - auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", - __func__, r.description().c_str()); - } - } -} - -static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, - LocationCapabilitiesMask mask) -{ - memset(&out, 0, sizeof(LocationOptions)); - out.size = sizeof(LocationOptions); - out.minInterval = (uint32_t)(in.periodNanos / 1000000L); - out.minDistance = 0; - out.mode = GNSS_SUPL_MODE_STANDALONE; - if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) - out.mode = GNSS_SUPL_MODE_MSA; - if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) - out.mode = GNSS_SUPL_MODE_MSB; -} - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gps/android/location_api/BatchingAPIClient.h b/gps/android/location_api/BatchingAPIClient.h deleted file mode 100644 index 5d64df3..0000000 --- a/gps/android/location_api/BatchingAPIClient.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef BATCHING_API_CLINET_H -#define BATCHING_API_CLINET_H - -#include -#include -#include - -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -class BatchingAPIClient : public LocationAPIClientBase -{ -public: - BatchingAPIClient(const sp& callback); - ~BatchingAPIClient(); - 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: - sp mGnssBatchingCbIface; - uint32_t mDefaultId; - LocationCapabilitiesMask mLocationCapabilitiesMask; -}; - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android -#endif // BATCHING_API_CLINET_H diff --git a/gps/android/location_api/GeofenceAPIClient.cpp b/gps/android/location_api/GeofenceAPIClient.cpp deleted file mode 100644 index 774a049..0000000 --- a/gps/android/location_api/GeofenceAPIClient.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define LOG_NDEBUG 0 -#define LOG_TAG "LocSvc_GeofenceApiClient" - -#include -#include - -#include "LocationUtil.h" -#include "GeofenceAPIClient.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; -using ::android::hardware::gnss::V1_0::GnssLocation; - -GeofenceAPIClient::GeofenceAPIClient(const sp& callback) : - LocationAPIClientBase(), - mGnssGeofencingCbIface(callback) -{ - LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); - - LocationCallbacks locationCallbacks; - memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); - locationCallbacks.size = sizeof(LocationCallbacks); - - locationCallbacks.trackingCb = nullptr; - locationCallbacks.batchingCb = nullptr; - - locationCallbacks.geofenceBreachCb = nullptr; - if (mGnssGeofencingCbIface != nullptr) { - locationCallbacks.geofenceBreachCb = - [this](GeofenceBreachNotification geofenceBreachNotification) { - onGeofenceBreachCb(geofenceBreachNotification); - }; - - locationCallbacks.geofenceStatusCb = - [this](GeofenceStatusNotification geofenceStatusNotification) { - onGeofenceStatusCb(geofenceStatusNotification); - }; - } - - locationCallbacks.gnssLocationInfoCb = nullptr; - locationCallbacks.gnssNiCb = nullptr; - locationCallbacks.gnssSvCb = nullptr; - locationCallbacks.gnssNmeaCb = nullptr; - locationCallbacks.gnssMeasurementsCb = nullptr; - - locAPISetCallbacks(locationCallbacks); -} - -void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude, - double radius_meters, int32_t last_transition, int32_t monitor_transitions, - uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) -{ - LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, - geofence_id, latitude, longitude, radius_meters, - last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms); - - GeofenceOption options; - memset(&options, 0, sizeof(GeofenceOption)); - options.size = sizeof(GeofenceOption); - if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) - options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; - if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) - options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT; - options.responsiveness = notification_responsiveness_ms; - - GeofenceInfo data; - data.size = sizeof(GeofenceInfo); - data.latitude = latitude; - data.longitude = longitude; - data.radius = radius_meters; - - LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); - if (LOCATION_ERROR_SUCCESS != err) { - onAddGeofencesCb(1, &err, &geofence_id); - } -} - -void GeofenceAPIClient::geofencePause(uint32_t geofence_id) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); - locAPIPauseGeofences(1, &geofence_id); -} - -void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) -{ - LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); - GeofenceBreachTypeMask mask = 0; - if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) - mask |= GEOFENCE_BREACH_ENTER_BIT; - if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) - mask |= GEOFENCE_BREACH_EXIT_BIT; - locAPIResumeGeofences(1, &geofence_id, &mask); -} - -void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); - locAPIRemoveGeofences(1, &geofence_id); -} - -void GeofenceAPIClient::geofenceRemoveAll() -{ - LOC_LOGD("%s]", __FUNCTION__); - // TODO locAPIRemoveAllGeofences(); -} - -// callbacks -void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) -{ - LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); - if (mGnssGeofencingCbIface != nullptr) { - for (size_t i = 0; i < geofenceBreachNotification.count; i++) { - GnssLocation gnssLocation; - convertGnssLocation(geofenceBreachNotification.location, gnssLocation); - - IGnssGeofenceCallback::GeofenceTransition transition; - if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) - transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; - else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) - transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; - else { - // continue with other breach if transition is - // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED - continue; - } - - auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( - geofenceBreachNotification.ids[i], gnssLocation, transition, - static_cast(geofenceBreachNotification.timestamp)); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); - if (mGnssGeofencingCbIface != nullptr) { - IGnssGeofenceCallback::GeofenceAvailability status = - IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; - if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { - status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; - } - GnssLocation gnssLocation; - memset(&gnssLocation, 0, sizeof(GnssLocation)); - auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", - __func__, r.description().c_str()); - } - } -} - -void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) -{ - LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); - if (mGnssGeofencingCbIface != nullptr) { - for (size_t i = 0; i < count; i++) { - IGnssGeofenceCallback::GeofenceStatus status = - IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; - if (errors[i] == LOCATION_ERROR_SUCCESS) - status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; - else if (errors[i] == LOCATION_ERROR_ID_EXISTS) - status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; - auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) -{ - LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); - if (mGnssGeofencingCbIface != nullptr) { - for (size_t i = 0; i < count; i++) { - IGnssGeofenceCallback::GeofenceStatus status = - IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; - if (errors[i] == LOCATION_ERROR_SUCCESS) - status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; - else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) - status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; - auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) -{ - LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); - if (mGnssGeofencingCbIface != nullptr) { - for (size_t i = 0; i < count; i++) { - IGnssGeofenceCallback::GeofenceStatus status = - IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; - if (errors[i] == LOCATION_ERROR_SUCCESS) - status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; - else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) - status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; - auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) -{ - LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); - if (mGnssGeofencingCbIface != nullptr) { - for (size_t i = 0; i < count; i++) { - IGnssGeofenceCallback::GeofenceStatus status = - IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; - if (errors[i] == LOCATION_ERROR_SUCCESS) - status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; - else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) - status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; - auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gps/android/location_api/GeofenceAPIClient.h b/gps/android/location_api/GeofenceAPIClient.h deleted file mode 100644 index dc99ddd..0000000 --- a/gps/android/location_api/GeofenceAPIClient.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GEOFENCE_API_CLINET_H -#define GEOFENCE_API_CLINET_H - - -#include -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::sp; - -class GeofenceAPIClient : public LocationAPIClientBase -{ -public: - GeofenceAPIClient(const sp& callback); - virtual ~GeofenceAPIClient() = default; - - 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: - sp mGnssGeofencingCbIface; -}; - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android -#endif // GEOFENCE_API_CLINET_H diff --git a/gps/android/location_api/GnssAPIClient.cpp b/gps/android/location_api/GnssAPIClient.cpp deleted file mode 100644 index 320ae15..0000000 --- a/gps/android/location_api/GnssAPIClient.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* 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_GnssAPIClient" - -#include -#include - -#include "LocationUtil.h" -#include "GnssAPIClient.h" -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::hardware::gnss::V1_0::IGnss; -using ::android::hardware::gnss::V1_0::IGnssCallback; -using ::android::hardware::gnss::V1_0::IGnssNiCallback; -using ::android::hardware::gnss::V1_0::GnssLocation; - -static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); - -GnssAPIClient::GnssAPIClient(const sp& gpsCb, - const sp& niCb) : - LocationAPIClientBase(), - mGnssCbIface(nullptr), - mGnssNiCbIface(nullptr), - mControlClient(new LocationAPIControlClient()), - mLocationCapabilitiesMask(0), - mLocationCapabilitiesCached(false) -{ - LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); - - // set default LocationOptions. - memset(&mLocationOptions, 0, sizeof(LocationOptions)); - mLocationOptions.size = sizeof(LocationOptions); - mLocationOptions.minInterval = 1000; - mLocationOptions.minDistance = 0; - mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE; - - gnssUpdateCallbacks(gpsCb, niCb); -} - -GnssAPIClient::~GnssAPIClient() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); - if (mControlClient) { - delete mControlClient; - mControlClient = nullptr; - } -} - -// for GpsInterface -void GnssAPIClient::gnssUpdateCallbacks(const sp& gpsCb, - const sp& niCb) -{ - LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); - - mMutex.lock(); - mGnssCbIface = gpsCb; - mGnssNiCbIface = niCb; - mMutex.unlock(); - - LocationCallbacks locationCallbacks; - memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); - locationCallbacks.size = sizeof(LocationCallbacks); - - locationCallbacks.trackingCb = nullptr; - if (mGnssCbIface != nullptr) { - locationCallbacks.trackingCb = [this](Location location) { - onTrackingCb(location); - }; - } - - locationCallbacks.batchingCb = nullptr; - locationCallbacks.geofenceBreachCb = nullptr; - locationCallbacks.geofenceStatusCb = nullptr; - locationCallbacks.gnssLocationInfoCb = nullptr; - - locationCallbacks.gnssNiCb = nullptr; - loc_core::ContextBase* context = - loc_core::LocDualContext::getLocFgContext( - NULL, NULL, - loc_core::LocDualContext::mLocationHalName, false); - 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(mLocationOptions); - 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) -{ - LOC_LOGD("%s]: (%d %d %d %d %d)", __FUNCTION__, - (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, preferredTimeMs); - bool retVal = true; - memset(&mLocationOptions, 0, sizeof(LocationOptions)); - mLocationOptions.size = sizeof(LocationOptions); - mLocationOptions.minInterval = minIntervalMs; - mLocationOptions.minDistance = preferredAccuracyMeters; - if (IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) { - mLocationOptions.minInterval = - std::numeric_limits::max(); - } - if (mode == IGnss::GnssPositionMode::STANDALONE) - mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE; - else if (mode == IGnss::GnssPositionMode::MS_BASED) - mLocationOptions.mode = GNSS_SUPL_MODE_MSB; - else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) - mLocationOptions.mode = GNSS_SUPL_MODE_MSA; - else { - LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); - retVal = false; - } - locAPIUpdateTrackingOptions(mLocationOptions); - return retVal; -} - -// for GpsNiInterface -void GnssAPIClient::gnssNiRespond(int32_t notifId, - IGnssNiCallback::GnssUserResponseType userResponse) -{ - LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast(userResponse)); - GnssNiResponse data = GNSS_NI_RESPONSE_IGNORE; - if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT) - data = GNSS_NI_RESPONSE_ACCEPT; - else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY) - data = GNSS_NI_RESPONSE_DENY; - else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP) - data = GNSS_NI_RESPONSE_NO_RESPONSE; - else { - LOC_LOGD("%s]: invalid GnssUserResponseType: %d", __FUNCTION__, (int)userResponse); - return; - } - 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; - - 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]: (%02x)", __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; - if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { - gnssInfo.yearOfHw = 2017; - } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { - gnssInfo.yearOfHw = 2016; - } else { - gnssInfo.yearOfHw = 2015; - } - 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) { - android::hardware::hidl_string nmeaString; - nmeaString.setToExternal(gnssNmeaNotification.nmea, gnssNmeaNotification.length); - auto r = gnssCbIface->gnssNmeaCb( - static_cast(gnssNmeaNotification.timestamp), nmeaString); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, - gnssNmeaNotification.nmea, gnssNmeaNotification.length, r.description().c_str()); - } - } -} - -void GnssAPIClient::onStartTrackingCb(LocationError error) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, error); - mMutex.lock(); - auto gnssCbIface(mGnssCbIface); - mMutex.unlock(); - - if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { - auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", - __func__, r.description().c_str()); - } - r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", - __func__, r.description().c_str()); - } - } -} - -void GnssAPIClient::onStopTrackingCb(LocationError error) -{ - LOC_LOGD("%s]: (%d)", __FUNCTION__, error); - mMutex.lock(); - auto gnssCbIface(mGnssCbIface); - mMutex.unlock(); - - if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { - auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", - __func__, r.description().c_str()); - } - r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); - if (!r.isOk()) { - LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", - __func__, r.description().c_str()); - } - } -} - -static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) -{ - memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); - out.numSvs = in.count; - if (out.numSvs > static_cast(V1_0::GnssMax::SVS_COUNT)) { - LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", - __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); - out.numSvs = static_cast(V1_0::GnssMax::SVS_COUNT); - } - for (size_t i = 0; i < out.numSvs; i++) { - IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; - info.svid = in.gnssSvs[i].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.svFlag = static_cast(IGnssCallback::GnssSvFlags::NONE); - if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) - info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; - if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) - info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; - if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) - info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; - } -} - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gps/android/location_api/GnssAPIClient.h b/gps/android/location_api/GnssAPIClient.h deleted file mode 100644 index 923cb48..0000000 --- a/gps/android/location_api/GnssAPIClient.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GNSS_API_CLINET_H -#define GNSS_API_CLINET_H - - -#include -#include -#include -#include -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::sp; - -class GnssAPIClient : public LocationAPIClientBase -{ -public: - GnssAPIClient(const sp& gpsCb, - const sp& niCb); - virtual ~GnssAPIClient(); - GnssAPIClient(const GnssAPIClient&) = delete; - GnssAPIClient& operator=(const GnssAPIClient&) = delete; - - // for GpsInterface - void gnssUpdateCallbacks(const sp& gpsCb, - const sp& niCb); - bool gnssStart(); - bool gnssStop(); - bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, - V1_0::IGnss::GnssPositionRecurrence recurrence, - uint32_t minIntervalMs, - uint32_t preferredAccuracyMeters, - uint32_t preferredTimeMs); - - // 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: - sp mGnssCbIface; - sp mGnssNiCbIface; - std::mutex mMutex; - LocationAPIControlClient* mControlClient; - LocationCapabilitiesMask mLocationCapabilitiesMask; - bool mLocationCapabilitiesCached; - - LocationOptions mLocationOptions; -}; - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android -#endif // GNSS_API_CLINET_H diff --git a/gps/android/location_api/LocationUtil.cpp b/gps/android/location_api/LocationUtil.cpp deleted file mode 100644 index 89681f2..0000000 --- a/gps/android/location_api/LocationUtil.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::hardware::gnss::V1_0::GnssLocation; -using ::android::hardware::gnss::V1_0::GnssConstellationType; -using ::android::hardware::gnss::V1_0::GnssLocationFlags; - -void convertGnssLocation(Location& in, GnssLocation& out) -{ - memset(&out, 0, sizeof(GnssLocation)); - if (in.flags & LOCATION_HAS_LAT_LONG_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG; - if (in.flags & LOCATION_HAS_ALTITUDE_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE; - if (in.flags & LOCATION_HAS_SPEED_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED; - if (in.flags & LOCATION_HAS_BEARING_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING; - if (in.flags & LOCATION_HAS_ACCURACY_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY; - if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY; - if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY; - if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) - out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY; - out.latitudeDegrees = in.latitude; - out.longitudeDegrees = in.longitude; - out.altitudeMeters = in.altitude; - out.speedMetersPerSec = in.speed; - out.bearingDegrees = in.bearing; - out.horizontalAccuracyMeters = in.accuracy; - out.verticalAccuracyMeters = in.verticalAccuracy; - out.speedAccuracyMetersPerSecond = in.speedAccuracy; - out.bearingAccuracyDegrees = in.bearingAccuracy; - out.timestamp = static_cast(in.timestamp); -} - -void convertGnssLocation(const GnssLocation& in, Location& out) -{ - memset(&out, 0, sizeof(out)); - if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) - out.flags |= LOCATION_HAS_LAT_LONG_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) - out.flags |= LOCATION_HAS_ALTITUDE_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) - out.flags |= LOCATION_HAS_SPEED_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) - out.flags |= LOCATION_HAS_BEARING_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) - out.flags |= LOCATION_HAS_ACCURACY_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) - out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) - out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; - if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) - out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; - out.latitude = in.latitudeDegrees; - out.longitude = in.longitudeDegrees; - out.altitude = in.altitudeMeters; - out.speed = in.speedMetersPerSec; - out.bearing = in.bearingDegrees; - out.accuracy = in.horizontalAccuracyMeters; - out.verticalAccuracy = in.verticalAccuracyMeters; - out.speedAccuracy = in.speedAccuracyMetersPerSecond; - out.bearingAccuracy = in.bearingAccuracyDegrees; - out.timestamp = static_cast(in.timestamp); -} - -void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) -{ - switch(in) { - case GNSS_SV_TYPE_GPS: - out = GnssConstellationType::GPS; - break; - case GNSS_SV_TYPE_SBAS: - out = GnssConstellationType::SBAS; - break; - case GNSS_SV_TYPE_GLONASS: - out = GnssConstellationType::GLONASS; - break; - case GNSS_SV_TYPE_QZSS: - out = GnssConstellationType::QZSS; - break; - case GNSS_SV_TYPE_BEIDOU: - out = GnssConstellationType::BEIDOU; - break; - case GNSS_SV_TYPE_GALILEO: - out = GnssConstellationType::GALILEO; - break; - case GNSS_SV_TYPE_UNKNOWN: - default: - out = GnssConstellationType::UNKNOWN; - break; - } -} - -void 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/location_api/LocationUtil.h b/gps/android/location_api/LocationUtil.h deleted file mode 100644 index 9e0cd36..0000000 --- a/gps/android/location_api/LocationUtil.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef LOCATION_UTIL_H -#define LOCATION_UTIL_H - -#include -#include -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -void convertGnssLocation(Location& in, V1_0::GnssLocation& out); -void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); -void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); -void 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/location_api/MeasurementAPIClient.cpp b/gps/android/location_api/MeasurementAPIClient.cpp deleted file mode 100644 index 823851d..0000000 --- a/gps/android/location_api/MeasurementAPIClient.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define LOG_NDEBUG 0 -#define LOG_TAG "LocSvc_MeasurementAPIClient" - -#include -#include - -#include "LocationUtil.h" -#include "MeasurementAPIClient.h" - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::hardware::gnss::V1_0::IGnssMeasurement; -using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback; - -static void convertGnssData(GnssMeasurementsNotification& in, - V1_0::IGnssMeasurementCallback::GnssData& out); -static void convertGnssMeasurement(GnssMeasurementsData& in, - V1_0::IGnssMeasurementCallback::GnssMeasurement& out); -static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out); - -MeasurementAPIClient::MeasurementAPIClient() : - mGnssMeasurementCbIface(nullptr), - mTracking(false) -{ - LOC_LOGD("%s]: ()", __FUNCTION__); -} - -MeasurementAPIClient::~MeasurementAPIClient() -{ - LOC_LOGD("%s]: ()", __FUNCTION__); -} - -// for GpsInterface -Return -MeasurementAPIClient::measurementSetCallback(const sp& callback) -{ - LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); - - mMutex.lock(); - mGnssMeasurementCbIface = callback; - mMutex.unlock(); - - return startTracking(); -} - -Return -MeasurementAPIClient::startTracking() -{ - LocationCallbacks locationCallbacks; - memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); - locationCallbacks.size = sizeof(LocationCallbacks); - - locationCallbacks.trackingCb = nullptr; - locationCallbacks.batchingCb = nullptr; - locationCallbacks.geofenceBreachCb = nullptr; - locationCallbacks.geofenceStatusCb = nullptr; - locationCallbacks.gnssLocationInfoCb = nullptr; - locationCallbacks.gnssNiCb = nullptr; - locationCallbacks.gnssSvCb = nullptr; - locationCallbacks.gnssNmeaCb = nullptr; - - locationCallbacks.gnssMeasurementsCb = nullptr; - if (mGnssMeasurementCbIface != nullptr) { - locationCallbacks.gnssMeasurementsCb = - [this](GnssMeasurementsNotification gnssMeasurementsNotification) { - onGnssMeasurementsCb(gnssMeasurementsNotification); - }; - } - - locAPISetCallbacks(locationCallbacks); - LocationOptions options; - memset(&options, 0, sizeof(LocationOptions)); - options.size = sizeof(LocationOptions); - options.minInterval = 1000; - options.mode = GNSS_SUPL_MODE_STANDALONE; - mTracking = true; - LOC_LOGD("%s]: start tracking session", __FUNCTION__); - locAPIStartTracking(options); - - return IGnssMeasurement::GnssMeasurementStatus::SUCCESS; -} - -// for GpsMeasurementInterface -void MeasurementAPIClient::measurementClose() { - LOC_LOGD("%s]: ()", __FUNCTION__); - mTracking = false; - locAPIStopTracking(); -} - -// callbacks -void MeasurementAPIClient::onGnssMeasurementsCb( - GnssMeasurementsNotification gnssMeasurementsNotification) -{ - LOC_LOGD("%s]: (count: %zu active: %d)", - __FUNCTION__, gnssMeasurementsNotification.count, mTracking); - if (mTracking) { - mMutex.lock(); - sp gnssMeasurementCbIface = nullptr; - if (mGnssMeasurementCbIface != nullptr) { - gnssMeasurementCbIface = mGnssMeasurementCbIface; - } - mMutex.unlock(); - - if (gnssMeasurementCbIface != nullptr) { - V1_0::IGnssMeasurementCallback::GnssData gnssData; - convertGnssData(gnssMeasurementsNotification, gnssData); - auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData); - if (!r.isOk()) { - LOC_LOGE("%s] Error from GnssMeasurementCb description=%s", - __func__, r.description().c_str()); - } - } - } -} - -static void convertGnssMeasurement(GnssMeasurementsData& in, - V1_0::IGnssMeasurementCallback::GnssMeasurement& out) -{ - memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement)); - if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR; - if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY; - if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES; - if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE; - if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY; - if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) - out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL; - out.svid = in.svId; - convertGnssConstellationType(in.svType, out.constellation); - out.timeOffsetNs = in.timeOffsetNs; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; - if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) - out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; - out.receivedSvTimeInNs = in.receivedSvTimeNs; - out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; - out.cN0DbHz = in.carrierToNoiseDbHz; - out.pseudorangeRateMps = in.pseudorangeRateMps; - out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; - if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) - out.accumulatedDeltaRangeState |= - IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; - if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) - out.accumulatedDeltaRangeState |= - IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; - if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) - out.accumulatedDeltaRangeState |= - IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; - out.accumulatedDeltaRangeM = in.adrMeters; - out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; - out.carrierFrequencyHz = in.carrierFrequencyHz; - out.carrierCycles = in.carrierCycles; - out.carrierPhase = in.carrierPhase; - out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; - uint8_t indicator = - static_cast(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); - if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) - indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; - if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) - indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; - out.multipathIndicator = - static_cast(indicator); - out.snrDb = in.signalToNoiseRatioDb; - out.agcLevelDb = in.agcLevelDb; -} - -static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) -{ - memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; - if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) - out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; - out.leapSecond = in.leapSecond; - out.timeNs = in.timeNs; - out.timeUncertaintyNs = in.timeUncertaintyNs; - out.fullBiasNs = in.fullBiasNs; - out.biasNs = in.biasNs; - out.biasUncertaintyNs = in.biasUncertaintyNs; - out.driftNsps = in.driftNsps; - out.driftUncertaintyNsps = in.driftUncertaintyNsps; - out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; -} - -static void convertGnssData(GnssMeasurementsNotification& in, - V1_0::IGnssMeasurementCallback::GnssData& out) -{ - out.measurementCount = in.count; - if (out.measurementCount > static_cast(V1_0::GnssMax::SVS_COUNT)) { - LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", - __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); - out.measurementCount = static_cast(V1_0::GnssMax::SVS_COUNT); - } - for (size_t i = 0; i < out.measurementCount; i++) { - convertGnssMeasurement(in.measurements[i], out.measurements[i]); - } - convertGnssClock(in.clock, out.clock); -} - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android diff --git a/gps/android/location_api/MeasurementAPIClient.h b/gps/android/location_api/MeasurementAPIClient.h deleted file mode 100644 index 08b4811..0000000 --- a/gps/android/location_api/MeasurementAPIClient.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation, nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef MEASUREMENT_API_CLINET_H -#define MEASUREMENT_API_CLINET_H - -#include -#include -#include -#include -#include - -namespace android { -namespace hardware { -namespace gnss { -namespace V1_0 { -namespace implementation { - -using ::android::sp; - -class MeasurementAPIClient : public LocationAPIClientBase -{ -public: - MeasurementAPIClient(); - virtual ~MeasurementAPIClient(); - MeasurementAPIClient(const MeasurementAPIClient&) = delete; - MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; - - // for GpsMeasurementInterface - Return measurementSetCallback( - const sp& callback); - void measurementClose(); - Return startTracking(); - - // callbacks we are interested in - void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final; - -private: - std::mutex mMutex; - sp mGnssMeasurementCbIface; - - bool mTracking; -}; - -} // namespace implementation -} // namespace V1_0 -} // namespace gnss -} // namespace hardware -} // namespace android -#endif // MEASUREMENT_API_CLINET_H diff --git a/gps/android/measurement_corrections/1.0/MeasurementCorrections.cpp b/gps/android/measurement_corrections/1.0/MeasurementCorrections.cpp new file mode 100644 index 0000000..2c93cb3 --- /dev/null +++ b/gps/android/measurement_corrections/1.0/MeasurementCorrections.cpp @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#define LOG_TAG "LocSvc_MeasurementCorrectionsInterface" + +#include +#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 MeasurementCorrections::setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& /*corrections*/) { + return true; +} + +Return MeasurementCorrections::setCallback( + const sp& /*callback*/) { + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace measurement_corrections +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/android/measurement_corrections/1.0/MeasurementCorrections.h b/gps/android/measurement_corrections/1.0/MeasurementCorrections.h new file mode 100644 index 0000000..ad534dc --- /dev/null +++ b/gps/android/measurement_corrections/1.0/MeasurementCorrections.h @@ -0,0 +1,76 @@ +/* + * 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_MeasurementCorrections_H +#define ANDROID_HARDWARE_GNSS_V1_0_MeasurementCorrections_H + +#include +#include +#include +#include + +#include + +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 setCorrections(const ::android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections& corrections) override; + +Return setCallback(const sp& 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/service.cpp b/gps/android/service.cpp deleted file mode 100644 index 6b0f602..0000000 --- a/gps/android/service.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 -#include - -using android::hardware::gnss::V1_0::IGnss; -using android::hardware::defaultPassthroughServiceImplementation; - -int main() { - return defaultPassthroughServiceImplementation(); -} diff --git a/gps/android/utils/Android.mk b/gps/android/utils/Android.mk new file mode 100644 index 0000000..bbcf512 --- /dev/null +++ b/gps/android/utils/Android.mk @@ -0,0 +1,38 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := liblocbatterylistener +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_CFLAGS += $(GNSS_CFLAGS) + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH) \ + +LOCAL_SRC_FILES:= \ + battery_listener.cpp +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libhidlbase \ + libcutils \ + libutils \ + android.hardware.health@1.0 \ + android.hardware.health@2.0 \ + android.hardware.power@1.2 \ + libbase + +LOCAL_STATIC_LIBRARIES := libhealthhalutils +LOCAL_CFLAGS += -DBATTERY_LISTENER_ENABLED + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := liblocbatterylistener_headers +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) + +include $(BUILD_HEADER_LIBRARY) + + diff --git a/gps/android/utils/battery_listener.cpp b/gps/android/utils/battery_listener.cpp new file mode 100644 index 0000000..f96dc70 --- /dev/null +++ b/gps/android/utils/battery_listener.cpp @@ -0,0 +1,273 @@ +/* +* 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" + +#include +#include +#include +#include +#include +using android::hardware::interfacesEqual; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::health::V1_0::BatteryStatus; +using android::hardware::health::V1_0::toString; +using android::hardware::health::V2_0::get_health_service; +using android::hardware::health::V2_0::HealthInfo; +using android::hardware::health::V2_0::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_0::IHealthInfoCallback, + public hardware::hidl_death_recipient { + typedef std::function cb_fn_t; + BatteryListenerImpl(cb_fn_t cb); + virtual ~BatteryListenerImpl (); + virtual hardware::Return healthInfoChanged( + const hardware::health::V2_0::HealthInfo& info); + virtual void serviceDied(uint64_t cookie, + const wp& who); + bool isCharging() { + std::lock_guard _l(mLock); + return statusToBool(mStatus); + } + private: + sp mHealth; + status_t init(); + BatteryStatus mStatus; + cb_fn_t mCb; + std::mutex mLock; + std::condition_variable mCond; + std::unique_ptr 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 = hardware::health::V2_0::get_health_service(); + if (mHealth != NULL) + break; + usleep(GET_HEALTH_SVC_WAIT_TIME_MS * 1000); + tries++; + } while(tries < GET_HEALTH_SVC_RETRY_CNT); + + if (mHealth == NULL) { + ALOGE("no health service found, retries %d", tries); + return NO_INIT; + } else { + ALOGI("Get health service in %d tries", tries); + } + mStatus = BatteryStatus::UNKNOWN; + auto ret = mHealth->getChargeStatus([&](Result r, BatteryStatus status) { + if (r != Result::SUCCESS) { + ALOGE("batterylistener: cannot get battery status"); + return; + } + mStatus = status; + }); + if (!ret.isOk()) + ALOGE("batterylistener: get charge status transaction error"); + + if (mStatus == BatteryStatus::UNKNOWN) + ALOGW("batterylistener: init: invalid battery status"); + mDone = false; + mThread = std::make_unique([this]() { + std::unique_lock 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); + ALOGI("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING"); + l.unlock(); + mCb(c); + l.lock(); + break; + } + } + }); + auto reg = mHealth->registerCallback(this); + if (!reg.isOk()) { + ALOGE("Transaction error in registeringCb to HealthHAL death: %s", + reg.description().c_str()); + } + + auto linked = mHealth->linkToDeath(this, 0 /* cookie */); + if (!linked.isOk() || linked == false) { + ALOGE("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 _l(mLock); + if (mHealth != NULL) { + mHealth->unregisterCallback(this); + auto r = mHealth->unlinkToDeath(this); + if (!r.isOk() || r == false) { + ALOGE("Transaction error in unregister to HealthHAL death: %s", + r.description().c_str()); + } + } + } + mDone = true; + if (NULL != mThread) { + mThread->join(); + } +} + +void BatteryListenerImpl::serviceDied(uint64_t cookie __unused, + const wp& who) +{ + { + std::lock_guard _l(mLock); + if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) { + ALOGE("health not initialized or unknown interface died"); + return; + } + ALOGI("health service died, reinit"); + mDone = true; + } + mHealth = NULL; + mCond.notify_one(); + if (NULL != mThread) { + mThread->join(); + } + std::lock_guard _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 BatteryListenerImpl::healthInfoChanged( + const hardware::health::V2_0::HealthInfo& info) +{ + ALOGV("healthInfoChanged: %d", info.legacy.batteryStatus); + std::unique_lock l(mLock); + if (info.legacy.batteryStatus != mStatus) { + mStatus = info.legacy.batteryStatus; + mCond.notify_one(); + } + return Void(); +} + +static sp batteryListener; +status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb) +{ + ALOGV("batteryPropertiesListenerInit entry"); + batteryListener = new BatteryListenerImpl(cb); + return NO_ERROR; +} + +status_t batteryPropertiesListenerDeinit() +{ + batteryListener.clear(); + return OK; +} + +bool batteryPropertiesListenerIsCharging() +{ + return batteryListener->isCharging(); +} + +} // namespace android + +void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) +{ + ALOGV("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/android/visibility_control/1.0/GnssVisibilityControl.cpp b/gps/android/visibility_control/1.0/GnssVisibilityControl.cpp new file mode 100644 index 0000000..5a8c697 --- /dev/null +++ b/gps/android/visibility_control/1.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 +#include +#include +#include "GnssVisibilityControl.h" +#include + +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 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 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/visibility_control/1.0/GnssVisibilityControl.h b/gps/android/visibility_control/1.0/GnssVisibilityControl.h new file mode 100644 index 0000000..9c26e38 --- /dev/null +++ b/gps/android/visibility_control/1.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 +#include +#include + +#include +#include +#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 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 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 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/batching/Android.mk b/gps/batching/Android.mk new file mode 100644 index 0000000..f3e8fe4 --- /dev/null +++ b/gps/batching/Android.mk @@ -0,0 +1,39 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libbatching +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_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + liblog \ + libloc_core \ + libgps.utils \ + libdl + +LOCAL_SRC_FILES += \ + location_batching.cpp \ + BatchingAdapter.cpp + +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + +LOCAL_PRELINK_MODULE := false + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID +endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE diff --git a/gps/batching/BatchingAdapter.cpp b/gps/batching/BatchingAdapter.cpp new file mode 100644 index 0000000..135f0ed --- /dev/null +++ b/gps/batching/BatchingAdapter.cpp @@ -0,0 +1,1050 @@ +/* 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_BatchingAdapter" + +#include +#include +#include +#include + +using namespace loc_core; + +BatchingAdapter::BatchingAdapter() : + LocAdapterBase(0, + LocContext::getLocContext( + NULL, + NULL, + LocContext::mLocationHalName, + false)), + 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 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 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 & 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 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(*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(*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 +#include +#include +#include + +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 TripSessionStatusMap; + typedef std::map 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 & 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/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/build/target_specific_features.mk b/gps/build/target_specific_features.mk index 1a00ef1..155431a 100644 --- a/gps/build/target_specific_features.mk +++ b/gps/build/target_specific_features.mk @@ -1,3 +1,73 @@ GNSS_CFLAGS := \ -Werror \ - -Wno-undefined-bool-conversion + -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 + +# GPS-HIDL +GNSS_HIDL_1_0_TARGET_LIST := msm8960 +GNSS_HIDL_1_0_TARGET_LIST += msm8974 +GNSS_HIDL_1_0_TARGET_LIST += msm8226 +GNSS_HIDL_1_0_TARGET_LIST += msm8610 +GNSS_HIDL_1_0_TARGET_LIST += apq8084 +GNSS_HIDL_1_0_TARGET_LIST += msm8916 +GNSS_HIDL_1_0_TARGET_LIST += msm8994 +GNSS_HIDL_1_0_TARGET_LIST += msm8909 +GNSS_HIDL_1_0_TARGET_LIST += msm8952 +GNSS_HIDL_1_0_TARGET_LIST += msm8992 +GNSS_HIDL_2_0_TARGET_LIST := msm8996 +GNSS_HIDL_2_0_TARGET_LIST += msm8937 +GNSS_HIDL_2_0_TARGET_LIST += msm8953 +GNSS_HIDL_2_0_TARGET_LIST += msm8998 +GNSS_HIDL_2_0_TARGET_LIST += apq8098_latv +GNSS_HIDL_2_0_TARGET_LIST += sdm710 +GNSS_HIDL_2_0_TARGET_LIST += qcs605 +GNSS_HIDL_2_0_TARGET_LIST += sdm845 +GNSS_HIDL_2_0_TARGET_LIST += sdm660 +GNSS_HIDL_2_0_TARGET_LIST += msmnile +GNSS_HIDL_2_0_TARGET_LIST += sdmshrike +GNSS_HIDL_2_0_TARGET_LIST += $(MSMSTEPPE) +GNSS_HIDL_2_0_TARGET_LIST += $(TRINKET) +GNSS_HIDL_2_0_TARGET_LIST += kona +GNSS_HIDL_2_0_TARGET_LIST += atoll +GNSS_HIDL_2_0_TARGET_LIST += lito +GNSS_HIDL_2_0_TARGET_LIST += bengal + +ifneq (,$(filter $(GNSS_HIDL_2_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) +GNSS_HIDL_VERSION = 2.0 +endif +ifneq (,$(filter $(GNSS_HIDL_1_0_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) +GNSS_HIDL_VERSION = 1.0 +endif +ifneq (,$(filter $(GNSS_HIDL_1_1_TARGET_LIST),$(TARGET_BOARD_PLATFORM))) +GNSS_HIDL_VERSION = 1.1 +endif + +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST := msm8937 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8953 +GNSS_HIDL_LEGACY_MEASURMENTS_TARGET_LIST += msm8996 +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 + +# Activate the following two lines for regression testing +#GNSS_SANITIZE := address cfi alignment bounds null unreachable integer +#GNSS_SANITIZE_DIAG := address cfi alignment bounds null unreachable integer diff --git a/gps/configure.ac b/gps/configure.ac deleted file mode 100644 index 0ab8e68..0000000 --- a/gps/configure.ac +++ /dev/null @@ -1,87 +0,0 @@ -# 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]) -# 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.mk b/gps/core/Android.mk index 1a4f51a..ce5d6a8 100644 --- a/gps/core/Android.mk +++ b/gps/core/Android.mk @@ -6,15 +6,12 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libloc_core +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_TAGS := optional -ifeq ($(TARGET_DEVICE),apq8026_lw) -LOCAL_CFLAGS += -DPDK_FEATURE_SET -else ifeq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET),true) -LOCAL_CFLAGS += -DPDK_FEATURE_SET -endif - LOCAL_SHARED_LIBRARIES := \ liblog \ libutils \ @@ -27,7 +24,7 @@ LOCAL_SRC_FILES += \ LocApiBase.cpp \ LocAdapterBase.cpp \ ContextBase.cpp \ - LocDualContext.cpp \ + LocContext.cpp \ loc_core_log.cpp \ data-items/DataItemsFactoryProxy.cpp \ SystemStatusOsObserver.cpp \ diff --git a/gps/core/ContextBase.cpp b/gps/core/ContextBase.cpp index 35e6585..7434590 100644 --- a/gps/core/ContextBase.cpp +++ b/gps/core/ContextBase.cpp @@ -40,8 +40,16 @@ 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]; const loc_param_s_type ContextBase::mGps_conf_table[] = { @@ -62,11 +70,28 @@ const loc_param_s_type ContextBase::mGps_conf_table[] = {"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'}, + {"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'}, }; const loc_param_s_type ContextBase::mSap_conf_table[] = @@ -85,72 +110,105 @@ const loc_param_s_type ContextBase::mSap_conf_table[] = {"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_USAGE", &mSap_conf.SENSOR_USAGE, NULL, 'n'}, - {"SENSOR_ALGORITHM_CONFIG_MASK", &mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK, NULL, 'n'}, - {"SENSOR_PROVIDER", &mSap_conf.SENSOR_PROVIDER, NULL, 'n'} + {"SENSOR_ALGORITHM_CONFIG_MASK", &mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK, NULL, 'n'} }; void ContextBase::readConfig() { - /*Defaults for gps.conf*/ - mGps_conf.INTERMEDIATE_POS = 0; - mGps_conf.ACCURACY_THRES = 0; - mGps_conf.NMEA_PROVIDER = 0; - mGps_conf.GPS_LOCK = 0; - mGps_conf.SUPL_VER = 0x10000; - mGps_conf.SUPL_MODE = 0x1; - mGps_conf.SUPL_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; - /*XTRA version check is disabled by default*/ - mGps_conf.XTRA_VERSION_CHECK=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; - - /*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_USAGE = 0; /* Enabled */ - 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; - /* default provider is SSC */ - mSap_conf.SENSOR_PROVIDER = 1; - - /* 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; - - UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table); - UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table); + 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; + /*XTRA version check is disabled by default*/ + mGps_conf.XTRA_VERSION_CHECK=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; + + UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table); + UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table); + + 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() { @@ -197,20 +255,25 @@ LBSProxyBase* ContextBase::getLBSProxy(const char* libName) 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(mMsgTask, exMask, this))) { + if (NULL == (locApi = mLBSProxy->getLocApi(exMask, this))) { void *handle = NULL; - //try to see if LocApiV02 is present - if ((handle = dlopen("libloc_api_v02.so", RTLD_NOW)) != NULL) { - LOC_LOGD("%s:%d]: libloc_api_v02.so is present", __func__, __LINE__); + + 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 for LocApiV02", __func__, - __LINE__); - locApi = (*getter)(mMsgTask, exMask, this); + LOC_LOGD("%s:%d]: getter is not NULL of %s", __func__, + __LINE__, libname); + locApi = (*getter)(exMask, this); } } // only RPC is the option now @@ -223,7 +286,7 @@ LocApiBase* ContextBase::createLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask) if (NULL != getter) { LOC_LOGD("%s:%d]: getter is not NULL in RPC", __func__, __LINE__); - locApi = (*getter)(mMsgTask, exMask, this); + locApi = (*getter)(exMask, this); } } } @@ -233,7 +296,7 @@ LocApiBase* ContextBase::createLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask) // locApi could still be NULL at this time // we would then create a dummy one if (NULL == locApi) { - locApi = new LocApiBase(mMsgTask, exMask, this); + locApi = new LocApiBase(exMask, this); } return locApi; @@ -249,4 +312,33 @@ ContextBase::ContextBase(const MsgTask* msgTask, { } +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)); + } + + 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 index dc64b6a..6701600 100644 --- a/gps/core/ContextBase.h +++ b/gps/core/ContextBase.h @@ -36,9 +36,6 @@ #include #include -#define MAX_XTRA_SERVER_URL_LENGTH (256) -#define MAX_SUPL_SERVER_URL_LENGTH (256) - /* GPS.conf support */ /* NOTE: the implementaiton of the parser casts number fields to 32 bit. To ensure all 'n' fields working, @@ -53,20 +50,31 @@ typedef struct loc_gps_cfg_s uint32_t CAPABILITIES; uint32_t LPP_PROFILE; uint32_t XTRA_VERSION_CHECK; - char XTRA_SERVER_1[MAX_XTRA_SERVER_URL_LENGTH]; - char XTRA_SERVER_2[MAX_XTRA_SERVER_URL_LENGTH]; - char XTRA_SERVER_3[MAX_XTRA_SERVER_URL_LENGTH]; + 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; - uint32_t GPS_LOCK; + 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[MAX_SUPL_SERVER_URL_LENGTH]; + 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; } loc_gps_cfg_s_type; /* NOTE: the implementaiton of the parser casts number @@ -89,7 +97,6 @@ typedef struct uint32_t SENSOR_GYRO_BATCHES_PER_SEC_HIGH; uint32_t SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH; uint32_t SENSOR_CONTROL_MODE; - uint32_t SENSOR_USAGE; uint32_t SENSOR_ALGORITHM_CONFIG_MASK; uint8_t ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID; double ACCEL_RANDOM_WALK_SPECTRAL_DENSITY; @@ -99,7 +106,6 @@ typedef struct double RATE_RANDOM_WALK_SPECTRAL_DENSITY; uint8_t VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID; double VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY; - uint32_t SENSOR_PROVIDER; } loc_sap_cfg_s_type; namespace loc_core { @@ -116,23 +122,28 @@ protected: 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() { delete mLocApi; delete mLBSProxy; } + 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 hasCPIExtendedCapabilities() { return mLBSProxy->hasCPIExtendedCapabilities(); } inline bool hasNativeXtraClient() { return mLBSProxy->hasNativeXtraClient(); } inline void modemPowerVote(bool power) const { return mLBSProxy->modemPowerVote(power); } - inline void requestUlp(LocAdapterBase* adapter, - unsigned long capabilities) { - mLBSProxy->requestUlp(adapter, capabilities); - } inline IzatDevId_t getIzatDevId() const { return mLBSProxy->getIzatDevId(); } @@ -140,12 +151,111 @@ public: 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; 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(); }; +struct LocApiResponse: LocMsg { + private: + ContextBase& mContext; + std::function mProcImpl; + inline virtual void proc() const { + mProcImpl(mLocationError); + } + protected: + LocationError mLocationError; + public: + inline LocApiResponse(ContextBase& context, + std::function procImpl ) : + mContext(context), mProcImpl(procImpl) {} + + void returnToSender(const LocationError err) { + mLocationError = err; + mContext.sendMsg(this); + } +}; + +struct LocApiCollectiveResponse: LocMsg { + private: + ContextBase& mContext; + std::function errs)> mProcImpl; + inline virtual void proc() const { + mProcImpl(mLocationErrors); + } + protected: + std::vector mLocationErrors; + public: + inline LocApiCollectiveResponse(ContextBase& context, + std::function errs)> procImpl ) : + mContext(context), mProcImpl(procImpl) {} + inline virtual ~LocApiCollectiveResponse() { + } + + void returnToSender(std::vector& errs) { + mLocationErrors = errs; + mContext.sendMsg(this); + } +}; + + +template +struct LocApiResponseData: LocMsg { + private: + ContextBase& mContext; + std::function mProcImpl; + inline virtual void proc() const { + mProcImpl(mLocationError, mData); + } + protected: + LocationError mLocationError; + DATA mData; + public: + inline LocApiResponseData(ContextBase& context, + std::function 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..ec881f6 --- /dev/null +++ b/gps/core/EngineHubProxyBase.h @@ -0,0 +1,127 @@ +/* Copyright (c) 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 ENGINE_HUB_PROXY_BASE_H +#define ENGINE_HUB_PROXY_BASE_H + +namespace loc_core { + +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 ¶ms) { + (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; + } +}; + +typedef std::function + GnssAdapterReportEnginePositionsEventCb; + +typedef std::function + GnssAdapterReportSvEventCb; + +typedef std::function + GnssAdapterReqAidingDataCb; + +// 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); + +} // namespace loc_core + +#endif // ENGINE_HUB_PROXY_BASE_H diff --git a/gps/core/LBSProxyBase.h b/gps/core/LBSProxyBase.h index 94ddd0f..564c60b 100644 --- a/gps/core/LBSProxyBase.h +++ b/gps/core/LBSProxyBase.h @@ -29,7 +29,6 @@ #ifndef IZAT_PROXY_BASE_H #define IZAT_PROXY_BASE_H #include -#include namespace loc_core { @@ -40,11 +39,9 @@ class ContextBase; class LBSProxyBase { friend class ContextBase; inline virtual LocApiBase* - getLocApi(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask, + getLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase* context) const { - (void)msgTask; (void)exMask; (void)context; return NULL; @@ -53,14 +50,7 @@ protected: inline LBSProxyBase() {} public: inline virtual ~LBSProxyBase() {} - inline virtual void requestUlp(LocAdapterBase* adapter, - unsigned long capabilities) const { - - (void)adapter; - (void)capabilities; - } inline virtual bool hasAgpsExtendedCapabilities() const { return false; } - inline virtual bool hasCPIExtendedCapabilities() const { return false; } inline virtual void modemPowerVote(bool power) const { (void)power; diff --git a/gps/core/LocAdapterBase.cpp b/gps/core/LocAdapterBase.cpp index d0da3da..1b844e5 100644 --- a/gps/core/LocAdapterBase.cpp +++ b/gps/core/LocAdapterBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2017The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-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 @@ -42,10 +42,12 @@ namespace loc_core { // 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, LocAdapterProxyBase *adapterProxyBase) : - mEvtMask(mask), mContext(context), + ContextBase* context, bool isMaster, + LocAdapterProxyBase *adapterProxyBase) : + mIsMaster(isMaster), mEvtMask(mask), mContext(context), mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase), - mMsgTask(context->getMsgTask()) + mMsgTask(context->getMsgTask()), + mIsEngineCapabilitiesKnown(ContextBase::sIsEngineCapabilitiesKnown) { mLocApi->addAdapter(this); } @@ -79,7 +81,9 @@ void LocAdapterBase:: const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask loc_technology_mask, - bool /*fromUlp*/) { + GnssDataNotification* pDataNotify, + int msInWeek) +{ if (mLocAdapterProxyBase != NULL) { mLocAdapterProxyBase->reportPositionEvent((UlpLocation&)location, (GpsLocationExtended&)locationExtended, @@ -91,24 +95,31 @@ void LocAdapterBase:: } void LocAdapterBase:: - reportSvEvent(const GnssSvNotification& /*svNotify*/, bool /*fromUlp*/) + reportSvEvent(const GnssSvNotification& /*svNotify*/, + bool /*fromEngineHub*/) DEFAULT_IMPL() void LocAdapterBase:: - reportSvMeasurementEvent(GnssSvMeasurementSet &/*svMeasurementSet*/) + reportSvPolynomialEvent(GnssSvPolynomial &/*svPolynomial*/) DEFAULT_IMPL() void LocAdapterBase:: - reportSvPolynomialEvent(GnssSvPolynomial &/*svPolynomial*/) + reportSvEphemerisEvent(GnssSvEphemerisReport &/*svEphemeris*/) DEFAULT_IMPL() + void LocAdapterBase:: reportStatus(LocGpsStatusValue /*status*/) DEFAULT_IMPL() void LocAdapterBase:: - reportNmeaEvent(const char* /*nmea*/, size_t /*length*/, bool /*fromUlp*/) + reportNmeaEvent(const char* /*nmea*/, size_t /*length*/) +DEFAULT_IMPL() + +void LocAdapterBase:: + reportDataEvent(const GnssDataNotification& /*dataNotify*/, + int /*msInWeek*/) DEFAULT_IMPL() bool LocAdapterBase:: @@ -116,6 +127,10 @@ bool LocAdapterBase:: const char* /*url3*/, const int /*maxlength*/) DEFAULT_IMPL(false) +void LocAdapterBase:: + reportLocationSystemInfoEvent(const LocationSystemInfo& /*locationSystemInfo*/) +DEFAULT_IMPL() + bool LocAdapterBase:: requestXtraData() DEFAULT_IMPL(false) @@ -129,7 +144,8 @@ bool LocAdapterBase:: DEFAULT_IMPL(false) bool LocAdapterBase:: - requestATL(int /*connHandle*/, LocAGpsType /*agps_type*/) + requestATL(int /*connHandle*/, LocAGpsType /*agps_type*/, + LocApnTypeMask /*apn_type_mask*/) DEFAULT_IMPL(false) bool LocAdapterBase:: @@ -137,32 +153,259 @@ bool LocAdapterBase:: DEFAULT_IMPL(false) bool LocAdapterBase:: - requestSuplES(int /*connHandle*/) + 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:: - reportDataCallOpened() + reportWwanZppFix(LocGpsLocation &/*zppLoc*/) DEFAULT_IMPL(false) bool LocAdapterBase:: - reportDataCallClosed() + 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() + bool LocAdapterBase:: - requestNiNotifyEvent(const GnssNiNotification &/*notify*/, const void* /*data*/) + requestOdcpiEvent(OdcpiRequestInfo& /*request*/) DEFAULT_IMPL(false) -void LocAdapterBase:: - reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& /*measurements*/, - int /*msInWeek*/) -DEFAULT_IMPL() +bool LocAdapterBase:: + reportGnssEngEnergyConsumedEvent(uint64_t /*energyConsumedSinceFirstBoot*/) +DEFAULT_IMPL(false) bool LocAdapterBase:: - reportWwanZppFix(LocGpsLocation &/*zppLoc*/) + reportDeleteAidingDataEvent(GnssAidingData & /*aidingData*/) DEFAULT_IMPL(false) bool LocAdapterBase:: - reportOdcpiRequestEvent(OdcpiRequestInfo& /*request*/) + 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; + } + } 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)); +} + } // namespace loc_core diff --git a/gps/core/LocAdapterBase.h b/gps/core/LocAdapterBase.h index 35fc48e..909b6fe 100644 --- a/gps/core/LocAdapterBase.h +++ b/gps/core/LocAdapterBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-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 @@ -30,11 +30,12 @@ #define LOC_API_ADAPTER_BASE_H #include -#include #include #include #include +#define MIN_TRACKING_INTERVAL (100) // 100 msec + typedef struct LocationSessionKey { LocationAPI* client; uint32_t id; @@ -50,7 +51,8 @@ inline bool operator ==(LocationSessionKey const& left, LocationSessionKey const inline bool operator !=(LocationSessionKey const& left, LocationSessionKey const& right) { return left.id != right.id || left.client != right.client; } -typedef std::map LocationSessionMap; + +typedef void (*removeClientCompleteCallback)(LocationAPI* client); namespace loc_core { @@ -59,6 +61,9 @@ 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; @@ -66,12 +71,28 @@ protected: LocAdapterProxyBase* mLocAdapterProxyBase; const MsgTask* mMsgTask; inline LocAdapterBase(const MsgTask* msgTask) : - mEvtMask(0), mContext(NULL), mLocApi(NULL), + mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL), mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {} + + /* ==== CLIENT ========================================================================= */ + typedef std::map ClientDataMap; + ClientDataMap mClientData; + std::vector 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); } LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, - ContextBase* context, LocAdapterProxyBase *adapterProxyBase = NULL); + ContextBase* context, bool isMaster = false, + LocAdapterProxyBase *adapterProxyBase = NULL); + inline LOC_API_ADAPTER_EVENT_MASK_T checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const { return mEvtMask & mask; @@ -106,54 +127,94 @@ public: mLocApi->updateEvtMask(); } + inline void updateNmeaMask(uint32_t mask) + { + mLocApi->updateNmeaMask(mask); + } + inline bool isFeatureSupported(uint8_t featureVal) { - return mLocApi->isFeatureSupported(featureVal); + return ContextBase::isFeatureSupported(featureVal); } uint32_t generateSessionId(); - // This will be overridden by the individual adapters - // if necessary. - inline virtual void setUlpProxyCommand(UlpProxyBase* ulp) { - - (void)ulp; + inline bool isAdapterMaster() { + return mIsMaster; } + + inline bool isEngineCapabilitiesKnown() { return mIsEngineCapabilitiesKnown;} + inline void setEngineCapabilitiesKnown(bool value) { mIsEngineCapabilitiesKnown = value;} + virtual void handleEngineUpEvent(); virtual void handleEngineDownEvent(); - inline virtual void setPositionModeCommand(LocPosMode& posMode) { - - (void)posMode; - } - virtual void startTrackingCommand() {} - virtual void stopTrackingCommand() {} - virtual void getZppCommand() {} virtual void reportPositionEvent(const UlpLocation& location, const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask loc_technology_mask, - bool fromUlp=false); - virtual void reportSvEvent(const GnssSvNotification& svNotify, bool fromUlp=false); - virtual void reportNmeaEvent(const char* nmea, size_t length, bool fromUlp=false); - virtual void reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet); + 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); + virtual bool requestATL(int connHandle, LocAGpsType agps_type, + LocApnTypeMask apn_type_mask); virtual bool releaseATL(int connHandle); - virtual bool requestSuplES(int connHandle); - virtual bool reportDataCallOpened(); - virtual bool reportDataCallClosed(); - virtual bool requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data); + virtual bool requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data, + const LocInEmergency emergencyState); inline virtual bool isInSession() { return false; } ContextBase* getContext() const { return mContext; } - virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, + virtual void reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements, int msInWeek); virtual bool reportWwanZppFix(LocGpsLocation &zppLoc); - virtual bool reportOdcpiRequestEvent(OdcpiRequestInfo& request); + virtual bool reportZppBestAvailableFix(LocGpsLocation &zppLoc, + GpsLocationExtended &location_extended, LocPosTechMask tech_mask); + virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config); + virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config); + 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); + }; } // namespace loc_core diff --git a/gps/core/LocAdapterProxyBase.h b/gps/core/LocAdapterProxyBase.h index 044f59b..727d424 100644 --- a/gps/core/LocAdapterProxyBase.h +++ b/gps/core/LocAdapterProxyBase.h @@ -40,8 +40,8 @@ private: LocAdapterBase *mLocAdapterBase; protected: inline LocAdapterProxyBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, - ContextBase* context): - mLocAdapterBase(new LocAdapterBase(mask, context, this)) { + ContextBase* context, bool isMaster = false): + mLocAdapterBase(new LocAdapterBase(mask, context, isMaster, this)) { } inline virtual ~LocAdapterProxyBase() { delete mLocAdapterBase; @@ -65,7 +65,6 @@ public: GpsLocationExtended &locationExtended, enum loc_sess_status status, LocPosTechMask loc_technology_mask) { - (void)location; (void)locationExtended; (void)status; diff --git a/gps/core/LocApiBase.cpp b/gps/core/LocApiBase.cpp index 426335d..8c79cf7 100644 --- a/gps/core/LocApiBase.cpp +++ b/gps/core/LocApiBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-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 @@ -31,10 +31,11 @@ #include #include +#include #include #include #include -#include +#include namespace loc_core { @@ -95,7 +96,10 @@ struct LocSsrMsg : public LocMsg { } inline virtual void proc() const { mLocApi->close(); - mLocApi->open(mLocApi->getEvtMask()); + 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"); @@ -107,13 +111,17 @@ struct LocSsrMsg : public LocMsg { struct LocOpenMsg : public LocMsg { LocApiBase* mLocApi; - inline LocOpenMsg(LocApiBase* locApi) : - LocMsg(), mLocApi(locApi) + LocAdapterBase* mAdapter; + inline LocOpenMsg(LocApiBase* locApi, LocAdapterBase* adapter = nullptr) : + LocMsg(), mLocApi(locApi), mAdapter(adapter) { locallog(); } inline virtual void proc() const { - mLocApi->open(mLocApi->getEvtMask()); + 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()); @@ -123,14 +131,37 @@ struct LocOpenMsg : public LocMsg { } }; -LocApiBase::LocApiBase(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T excludedMask, +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) : - mMsgTask(msgTask), mContext(context), mSupportedMsg(0), + mContext(context), mMask(0), mExcludedMask(excludedMask) { memset(mLocAdapters, 0, sizeof(mLocAdapters)); - memset(mFeaturesSupported, 0, sizeof(mFeaturesSupported)); + + android_atomic_inc(&mMsgTaskRefCount); + if (nullptr == mMsgTask) { + mMsgTask = new MsgTask("LocApiMsgTask", false); + } } LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::getEvtMask() @@ -142,6 +173,18 @@ LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::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; @@ -155,12 +198,41 @@ bool LocApiBase::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; - mMsgTask->sendMsg(new LocOpenMsg(this)); + sendMsg(new LocOpenMsg(this, adapter)); break; } } @@ -193,10 +265,10 @@ void LocApiBase::removeAdapter(LocAdapterBase* adapter) // if we have an empty list of adapters if (0 == i) { - close(); + sendMsg(new LocCloseMsg(this)); } else { // else we need to remove the bit - mMsgTask->sendMsg(new LocOpenMsg(this)); + sendMsg(new LocOpenMsg(this)); } } } @@ -204,22 +276,43 @@ void LocApiBase::removeAdapter(LocAdapterBase* adapter) void LocApiBase::updateEvtMask() { - open(getEvtMask()); + sendMsg(new LocOpenMsg(this)); } -void LocApiBase::handleEngineUpEvent() +void LocApiBase::updateNmeaMask(uint32_t mask) { - // This will take care of renegotiating the loc handle - mMsgTask->sendMsg(new LocSsrMsg(this)); + 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(); + } + }; - LocDualContext::injectFeatureConfig(mContext); + 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()); } @@ -227,21 +320,22 @@ void LocApiBase::handleEngineDownEvent() void LocApiBase::reportPosition(UlpLocation& location, GpsLocationExtended& locationExtended, enum loc_sess_status status, - LocPosTechMask loc_technology_mask) + 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 rawDataSize: %d\n rawData: %p\n " + "timestamp: %" PRId64 "\n" "Session status: %d\n Technology mask: %u\n " "SV used in fix (gps/glo/bds/gal/qzss) : \ - (%" PRIx64 "/%" PRIx64 "/%" PRIx64 "/%" PRIx64 "/%" 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, location.rawDataSize, - location.rawData, status, loc_technology_mask, + 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, @@ -250,7 +344,8 @@ void LocApiBase::reportPosition(UlpLocation& location, // loop through adapters, and deliver to all adapters. TO_ALL_LOCADAPTERS( mLocAdapters[i]->reportPositionEvent(location, locationExtended, - status, loc_technology_mask) + status, loc_technology_mask, + pDataNotify, msInWeek) ); } @@ -260,19 +355,57 @@ void LocApiBase::reportWwanZppFix(LocGpsLocation &zppLoc) TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportWwanZppFix(zppLoc)); } -void LocApiBase::reportOdcpiRequest(OdcpiRequestInfo& request) +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_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportOdcpiRequestEvent(request)); + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNfwNotificationEvent(notification)); + } void LocApiBase::reportSv(GnssSvNotification& svNotify) { const char* constellationString[] = { "Unknown", "GPS", "SBAS", "GLONASS", - "QZSS", "BEIDOU", "GALILEO" }; + "QZSS", "BEIDOU", "GALILEO", "NAVIC" }; // print the SV info before delivering - LOC_LOGV("num sv: %zu\n" + LOC_LOGV("num sv: %u\n" " sv: constellation svid cN0" " elevation azimuth flags", svNotify.count); @@ -281,14 +414,19 @@ void LocApiBase::reportSv(GnssSvNotification& svNotify) sizeof(constellationString) / sizeof(constellationString[0]) - 1) { svNotify.gnssSvs[i].type = GNSS_SV_TYPE_UNKNOWN; } - LOC_LOGV(" %03zu: %*s %02d %f %f %f 0x%02X", + // Display what we report to clients + uint16_t displaySvId = GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[i].type ? + svNotify.gnssSvs[i].svId + QZSS_SV_PRN_MIN - 1 : + svNotify.gnssSvs[i].svId; + LOC_LOGV(" %03zu: %*s %02d %f %f %f %f 0x%02X", i, 13, constellationString[svNotify.gnssSvs[i].type], - svNotify.gnssSvs[i].svId, + displaySvId, svNotify.gnssSvs[i].cN0Dbhz, svNotify.gnssSvs[i].elevation, svNotify.gnssSvs[i].azimuth, + svNotify.gnssSvs[i].carrierFrequencyHz, svNotify.gnssSvs[i].gnssSvOptionsMask); } // loop through adapters, and deliver to all adapters. @@ -297,19 +435,19 @@ void LocApiBase::reportSv(GnssSvNotification& svNotify) ); } -void LocApiBase::reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet) +void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial) { // loop through adapters, and deliver to all adapters. TO_ALL_LOCADAPTERS( - mLocAdapters[i]->reportSvMeasurementEvent(svMeasurementSet) + mLocAdapters[i]->reportSvPolynomialEvent(svPolynomial) ); } -void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial) +void LocApiBase::reportSvEphemeris(GnssSvEphemerisReport & svEphemeris) { // loop through adapters, and deliver to all adapters. TO_ALL_LOCADAPTERS( - mLocAdapters[i]->reportSvPolynomialEvent(svPolynomial) + mLocAdapters[i]->reportSvEphemerisEvent(svEphemeris) ); } @@ -319,6 +457,12 @@ void LocApiBase::reportStatus(LocGpsStatusValue status) 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. @@ -333,6 +477,12 @@ void LocApiBase::reportXtraServer(const char* url1, const char* url2, } +void LocApiBase::reportLocationSystemInfo(const LocationSystemInfo& locationSystemInfo) +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationSystemInfoEvent(locationSystemInfo)); +} + void LocApiBase::requestXtraData() { // loop through adapters, and deliver to the first handling adapter. @@ -351,10 +501,12 @@ void LocApiBase::requestLocation() TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestLocation()); } -void LocApiBase::requestATL(int connHandle, LocAGpsType agps_type) +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)); + TO_1ST_HANDLING_LOCADAPTERS( + mLocAdapters[i]->requestATL(connHandle, agps_type, apn_type_mask)); } void LocApiBase::releaseATL(int connHandle) @@ -363,145 +515,160 @@ void LocApiBase::releaseATL(int connHandle) TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->releaseATL(connHandle)); } -void LocApiBase::requestSuplES(int connHandle) +void LocApiBase::requestNiNotify(GnssNiNotification ¬ify, const void* data, + const LocInEmergency emergencyState) { // loop through adapters, and deliver to the first handling adapter. - TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestSuplES(connHandle)); + TO_1ST_HANDLING_LOCADAPTERS( + mLocAdapters[i]->requestNiNotifyEvent(notify, + data, + emergencyState)); } -void LocApiBase::reportDataCallOpened() +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 the first handling adapter. - TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallOpened()); + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementsEvent(gnssMeasurements, msInWeek)); } -void LocApiBase::reportDataCallClosed() +void LocApiBase::reportGnssSvIdConfig(const GnssSvIdConfig& config) { - // loop through adapters, and deliver to the first handling adapter. - TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallClosed()); + // Print the config + LOC_LOGv("gloBlacklistSvMask: %" PRIu64 ", bdsBlacklistSvMask: %" PRIu64 ",\n" + "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64, + config.gloBlacklistSvMask, config.bdsBlacklistSvMask, + config.qzssBlacklistSvMask, config.galBlacklistSvMask); + + // Loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvIdConfigEvent(config)); } -void LocApiBase::requestNiNotify(GnssNiNotification ¬ify, const void* data) +void LocApiBase::reportGnssSvTypeConfig(const GnssSvTypeConfig& config) { - // loop through adapters, and deliver to the first handling adapter. - TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestNiNotifyEvent(notify, data)); + // 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::saveSupportedMsgList(uint64_t supportedMsgList) +void LocApiBase::geofenceBreach(size_t count, uint32_t* hwIds, Location& location, + GeofenceBreachType breachType, uint64_t timestamp) { - mSupportedMsg = supportedMsgList; + TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceBreachEvent(count, hwIds, location, breachType, + timestamp)); } -void LocApiBase::saveSupportedFeatureList(uint8_t *featureList) +void LocApiBase::geofenceStatus(GeofenceStatusAvailable available) { - memcpy((void *)mFeaturesSupported, (void *)featureList, sizeof(mFeaturesSupported)); + TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceStatusEvent(available)); } -void* LocApiBase :: getSibling() - DEFAULT_IMPL(NULL) +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)); +} -LocApiProxyBase* LocApiBase :: getLocApiProxy() - DEFAULT_IMPL(NULL) +void LocApiBase::reportLocations(Location* locations, size_t count, BatchingMode batchingMode) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationsEvent(locations, count, batchingMode)); +} -void LocApiBase::reportGnssMeasurementData(GnssMeasurementsNotification& measurements, - int msInWeek) +void LocApiBase::reportCompletedTrips(uint32_t accumulated_distance) { - // loop through adapters, and deliver to all adapters. - TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementDataEvent(measurements, msInWeek)); + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportCompletedTripsEvent(accumulated_distance)); } -enum loc_api_adapter_err LocApiBase:: - open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +void LocApiBase::handleBatchStatusEvent(BatchingStatus batchStatus) +{ + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportBatchStatusChangeEvent(batchStatus)); +} -enum loc_api_adapter_err LocApiBase:: - close() -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) enum loc_api_adapter_err LocApiBase:: - startFix(const LocPosMode& /*posMode*/) + open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) enum loc_api_adapter_err LocApiBase:: - stopFix() + close() DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) -LocationError LocApiBase:: - deleteAidingData(const GnssAidingData& /*data*/) -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +void LocApiBase::startFix(const LocPosMode& /*posMode*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: - enableData(int /*enable*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +void LocApiBase::stopFix(LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: - setAPN(char* /*apn*/, int /*len*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +void LocApiBase:: + deleteAidingData(const GnssAidingData& /*data*/, LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: +void LocApiBase:: injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: - injectPosition(const Location& /*location*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +void LocApiBase:: + injectPosition(const Location& /*location*/, bool /*onDemandCpi*/) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: +void LocApiBase:: + injectPosition(const GnssLocationInfoNotification & /*locationInfo*/, bool /*onDemandCpi*/) +DEFAULT_IMPL() + +void LocApiBase:: setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +DEFAULT_IMPL() enum loc_api_adapter_err LocApiBase:: setXtraData(char* /*data*/, int /*length*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) -enum loc_api_adapter_err LocApiBase:: - requestXtraServer() -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) - -enum loc_api_adapter_err LocApiBase:: - atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, - AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +void LocApiBase:: + atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, uint32_t /*apnLen*/, + AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/, + LocApnTypeMask /*mask*/) +DEFAULT_IMPL() -enum loc_api_adapter_err LocApiBase:: +void LocApiBase:: atlCloseStatus(int /*handle*/, int /*is_succ*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) - -enum loc_api_adapter_err LocApiBase:: - setPositionMode(const LocPosMode& /*posMode*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +DEFAULT_IMPL() LocationError LocApiBase:: - setServer(const char* /*url*/, int /*len*/) + setServerSync(const char* /*url*/, int /*len*/, LocServerType /*type*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) LocationError LocApiBase:: - setServer(unsigned int /*ip*/, int /*port*/, LocServerType /*type*/) + setServerSync(unsigned int /*ip*/, int /*port*/, LocServerType /*type*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -LocationError LocApiBase:: +void LocApiBase:: informNiResponse(GnssNiResponse /*userResponse*/, const void* /*passThroughData*/) -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +DEFAULT_IMPL() LocationError LocApiBase:: - setSUPLVersion(GnssConfigSuplVersion /*version*/) + setSUPLVersionSync(GnssConfigSuplVersion /*version*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) enum loc_api_adapter_err LocApiBase:: - setNMEATypes (uint32_t /*typesMask*/) + setNMEATypesSync (uint32_t /*typesMask*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) LocationError LocApiBase:: - setLPPConfig(GnssConfigLppProfile /*profile*/) + setLPPConfigSync(GnssConfigLppProfile /*profile*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -enum loc_api_adapter_err LocApiBase:: - setSensorControlConfig(int /*sensorUsage*/, - int /*sensorProvider*/) -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) enum loc_api_adapter_err LocApiBase:: - setSensorProperties(bool /*gyroBiasVarianceRandomWalk_valid*/, + setSensorPropertiesSync(bool /*gyroBiasVarianceRandomWalk_valid*/, float /*gyroBiasVarianceRandomWalk*/, bool /*accelBiasVarianceRandomWalk_valid*/, float /*accelBiasVarianceRandomWalk*/, @@ -514,7 +681,7 @@ enum loc_api_adapter_err LocApiBase:: DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) enum loc_api_adapter_err LocApiBase:: - setSensorPerfControlConfig(int /*controlMode*/, + setSensorPerfControlConfigSync(int /*controlMode*/, int /*accelSamplesPerBatch*/, int /*accelBatchesPerSec*/, int /*gyroSamplesPerBatch*/, @@ -527,88 +694,184 @@ enum loc_api_adapter_err LocApiBase:: DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) LocationError LocApiBase:: - setAGLONASSProtocol(GnssConfigAGlonassPositionProtocolMask /*aGlonassProtocol*/) + setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask /*aGlonassProtocol*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) LocationError LocApiBase:: - setLPPeProtocolCp(GnssConfigLppeControlPlaneMask /*lppeCP*/) + setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask /*lppeCP*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) LocationError LocApiBase:: - setLPPeProtocolUp(GnssConfigLppeUserPlaneMask /*lppeUP*/) + setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask /*lppeUP*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -enum loc_api_adapter_err LocApiBase:: - getWwanZppFix() -DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +GnssConfigSuplVersion LocApiBase::convertSuplVersion(const uint32_t /*suplVersion*/) +DEFAULT_IMPL(GNSS_CONFIG_SUPL_VERSION_1_0_0) -enum loc_api_adapter_err LocApiBase:: - getBestAvailableZppFix(LocGpsLocation& zppLoc) -{ - memset(&zppLoc, 0, sizeof(zppLoc)); - DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) -} +GnssConfigLppProfile LocApiBase::convertLppProfile(const uint32_t /*lppProfile*/) +DEFAULT_IMPL(GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE) -enum loc_api_adapter_err LocApiBase:: - getBestAvailableZppFix(LocGpsLocation & zppLoc, GpsLocationExtended & locationExtended, - LocPosTechMask & tech_mask) -{ - memset(&zppLoc, 0, sizeof(zppLoc)); - memset(&tech_mask, 0, sizeof(tech_mask)); - memset(&locationExtended, 0, sizeof (locationExtended)); - DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) -} +GnssConfigLppeControlPlaneMask LocApiBase::convertLppeCp(const uint32_t /*lppeControlPlaneMask*/) +DEFAULT_IMPL(0) -int LocApiBase:: - initDataServiceClient(bool /*isDueToSsr*/) -DEFAULT_IMPL(-1) +GnssConfigLppeUserPlaneMask LocApiBase::convertLppeUp(const uint32_t /*lppeUserPlaneMask*/) +DEFAULT_IMPL(0) -int LocApiBase:: - openAndStartDataCall() -DEFAULT_IMPL(-1) - -void LocApiBase:: - stopDataCall() -DEFAULT_IMPL() +LocationError LocApiBase::setEmergencyExtensionWindowSync( + const uint32_t /*emergencyExtensionSeconds*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) void LocApiBase:: - closeDataCall() + getWwanZppFix() DEFAULT_IMPL() void LocApiBase:: - releaseDataServiceClient() + getBestAvailableZppFix() DEFAULT_IMPL() LocationError LocApiBase:: - setGpsLock(GnssConfigGpsLock /*lock*/) + setGpsLockSync(GnssConfigGpsLock /*lock*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +void LocApiBase:: + requestForAidingData(GnssAidingDataSvMask /*svDataMask*/) +DEFAULT_IMPL() + void LocApiBase:: installAGpsCert(const LocDerEncodedCertificate* /*pData*/, size_t /*length*/, uint32_t /*slotBitMask*/) DEFAULT_IMPL() -int LocApiBase:: - getGpsLock() -DEFAULT_IMPL(-1) +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*/) +DEFAULT_IMPL() + +void LocApiBase::getBlacklistSv() +DEFAULT_IMPL() + +void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/) +DEFAULT_IMPL() + +void LocApiBase::getConstellationControl() +DEFAULT_IMPL() + +void LocApiBase::resetConstellationControl() +DEFAULT_IMPL() LocationError LocApiBase:: - setXtraVersionCheck(uint32_t /*check*/) + setConstrainedTuncMode(bool /*enabled*/, + float /*tuncConstraint*/, + uint32_t /*energyBudget*/) DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -bool LocApiBase:: - gnssConstellationConfig() -DEFAULT_IMPL(false) +LocationError LocApiBase:: + setPositionAssistedClockEstimatorMode(bool /*enabled*/) +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) -bool LocApiBase:: - isFeatureSupported(uint8_t featureVal) -{ - uint8_t arrayIndex = featureVal >> 3; - uint8_t bitPos = featureVal & 7; +LocationError LocApiBase::getGnssEnergyConsumed() +DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + + +void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/, + const GeofenceInfo& /*info*/, + LocApiResponseData* /*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* /*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() - if (arrayIndex >= MAX_FEATURE_LENGTH) return false; - return ((mFeaturesSupported[arrayIndex] >> bitPos ) & 0x1); -} } // namespace loc_core diff --git a/gps/core/LocApiBase.h b/gps/core/LocApiBase.h index 6563dea..6dac585 100644 --- a/gps/core/LocApiBase.h +++ b/gps/core/LocApiBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014, 2016-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 @@ -34,10 +34,14 @@ #include #include #include +#include #include namespace loc_core { + class ContextBase; +struct LocApiResponse; +template struct LocApiResponseData; int hexcode(char *hexstring, int string_size, const char *data, int data_size); @@ -66,6 +70,28 @@ 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 mProcImpl; + inline virtual void proc() const { + mProcImpl(); + } + public: + inline LocApiMsg(std::function procImpl ) : + mProcImpl(procImpl) {} +}; + class LocApiProxyBase { public: inline LocApiProxyBase() {} @@ -78,31 +104,57 @@ class LocApiBase { //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; - const MsgTask* mMsgTask; - ContextBase *mContext; + static MsgTask* mMsgTask; + static volatile int32_t mMsgTaskRefCount; LocAdapterBase* mLocAdapters[MAX_ADAPTERS]; - uint64_t mSupportedMsg; - uint8_t mFeaturesSupported[MAX_FEATURE_LENGTH]; 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; - LocApiBase(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T excludedMask, + uint32_t mNmeaMask; + LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask, ContextBase* context = NULL); - inline virtual ~LocApiBase() { close(); } + inline virtual ~LocApiBase() { + android_atomic_dec(&mMsgTaskRefCount); + if (nullptr != mMsgTask && 0 == mMsgTaskRefCount) { + mMsgTask->destroy(); + mMsgTask = nullptr; + } + } bool isInSession(); const LOC_API_ADAPTER_EVENT_MASK_T mExcludedMask; + bool isMaster(); public: inline void sendMsg(const LocMsg* msg) const { - mMsgTask->sendMsg(msg); + 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); @@ -113,155 +165,156 @@ public: GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask loc_technology_mask = - LOC_POS_TECH_MASK_DEFAULT); + LOC_POS_TECH_MASK_DEFAULT, + GnssDataNotification* pDataNotify = nullptr, + int msInWeek = -1); void reportSv(GnssSvNotification& svNotify); - void reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet); 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); + void requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask); void releaseATL(int connHandle); - void requestSuplES(int connHandle); - void reportDataCallOpened(); - void reportDataCallClosed(); - void requestNiNotify(GnssNiNotification ¬ify, const void* data); - void saveSupportedMsgList(uint64_t supportedMsgList); - void reportGnssMeasurementData(GnssMeasurementsNotification& measurements, int msInWeek); - void saveSupportedFeatureList(uint8_t *featureList); + void requestNiNotify(GnssNiNotification ¬ify, const void* data, + const LocInEmergency emergencyState); + void reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek); void reportWwanZppFix(LocGpsLocation &zppLoc); - void reportOdcpiRequest(OdcpiRequestInfo& request); + 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); - // downward calls - // All below functions are to be defined by adapter specific modules: - // RPC, QMI, etc. The default implementation is empty. + 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 enum loc_api_adapter_err - startFix(const LocPosMode& posMode); - virtual enum loc_api_adapter_err - stopFix(); - virtual LocationError - deleteAidingData(const GnssAidingData& data); - virtual enum loc_api_adapter_err - enableData(int enable); - virtual enum loc_api_adapter_err - setAPN(char* apn, int len); - virtual enum loc_api_adapter_err - injectPosition(double latitude, double longitude, float accuracy); - virtual enum loc_api_adapter_err - injectPosition(const Location& location); - virtual enum loc_api_adapter_err - setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty); - virtual enum loc_api_adapter_err - setXtraData(char* data, int length); - virtual enum loc_api_adapter_err - requestXtraServer(); - virtual enum loc_api_adapter_err - atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bear, LocAGpsType agpsType); - virtual enum loc_api_adapter_err - atlCloseStatus(int handle, int is_succ); - virtual enum loc_api_adapter_err - setPositionMode(const LocPosMode& posMode); - virtual LocationError - setServer(const char* url, int len); - virtual LocationError - setServer(unsigned int ip, int port, - LocServerType type); + 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); + 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 enum loc_api_adapter_err setXtraData(char* data, int length); + 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(GnssConfigLppProfile profile); + 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 - informNiResponse(GnssNiResponse userResponse, const void* passThroughData); - virtual LocationError setSUPLVersion(GnssConfigSuplVersion version); - virtual enum loc_api_adapter_err - setNMEATypes (uint32_t typesMask); - virtual LocationError setLPPConfig(GnssConfigLppProfile profile); - virtual enum loc_api_adapter_err - setSensorControlConfig(int sensorUsage, int sensorProvider); - virtual enum loc_api_adapter_err - setSensorProperties(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 - setSensorPerfControlConfig(int controlMode, - int accelSamplesPerBatch, - int accelBatchesPerSec, - int gyroSamplesPerBatch, - int gyroBatchesPerSec, - int accelSamplesPerBatchHigh, - int accelBatchesPerSecHigh, - int gyroSamplesPerBatchHigh, - int gyroBatchesPerSecHigh, - int algorithmConfig); - virtual LocationError - setAGLONASSProtocol(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol); - virtual LocationError setLPPeProtocolCp(GnssConfigLppeControlPlaneMask lppeCP); - virtual LocationError setLPPeProtocolUp(GnssConfigLppeUserPlaneMask lppeUP); - virtual enum loc_api_adapter_err - getWwanZppFix(); - virtual enum loc_api_adapter_err - getBestAvailableZppFix(LocGpsLocation & zppLoc); - virtual enum loc_api_adapter_err - getBestAvailableZppFix(LocGpsLocation & zppLoc, GpsLocationExtended & locationExtended, - LocPosTechMask & tech_mask); - virtual int initDataServiceClient(bool isDueToSsr); - virtual int openAndStartDataCall(); - virtual void stopDataCall(); - virtual void closeDataCall(); - virtual void releaseDataServiceClient(); - virtual void installAGpsCert(const LocDerEncodedCertificate* pData, - size_t length, - uint32_t slotBitMask); - inline virtual void setInSession(bool inSession) { + setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol); + virtual LocationError setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP); + virtual LocationError setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP); + virtual GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion); + virtual GnssConfigLppProfile convertLppProfile(const uint32_t lppProfile); + virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask); + virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask); + virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds); - (void)inSession; - } - inline bool isMessageSupported (LocCheckingMessagesID msgID) const { + virtual void getWwanZppFix(); + virtual void getBestAvailableZppFix(); + virtual void installAGpsCert(const LocDerEncodedCertificate* pData, size_t length, + uint32_t slotBitMask); + 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); + virtual void getBlacklistSv(); + virtual void setConstellationControl(const GnssSvTypeConfig& config); + virtual void getConstellationControl(); + virtual void resetConstellationControl(); + virtual LocationError setConstrainedTuncMode(bool enabled, float tuncConstraint, + uint32_t energyBudget); + virtual LocationError setPositionAssistedClockEstimatorMode(bool enabled); + virtual LocationError getGnssEnergyConsumed(); - // confirm if msgID is not larger than the number of bits in - // mSupportedMsg - if ((uint64_t)msgID > (sizeof(mSupportedMsg) << 3)) { - return false; - } else { - uint32_t messageChecker = 1 << msgID; - return (messageChecker & mSupportedMsg) == messageChecker; - } - } + virtual void addGeofence(uint32_t clientId, const GeofenceOption& options, + const GeofenceInfo& info, LocApiResponseData* 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); - void updateEvtMask(); + 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* adapterResponseData); + virtual void setBatchSize(size_t size); + virtual void setTripBatchSize(size_t size); + virtual void addToCallQueue(LocApiResponse* adapterResponse); - virtual LocationError setGpsLock(GnssConfigGpsLock lock); - /* - Returns - Current value of GPS Lock on success - -1 on failure - */ - virtual int getGpsLock(void); - - virtual LocationError setXtraVersionCheck(uint32_t check); - /* - Check if the modem support the service - */ - virtual bool gnssConstellationConfig(); + void updateEvtMask(); + void updateNmeaMask(uint32_t mask); - /* - Check if a feature is supported - */ - bool isFeatureSupported(uint8_t featureVal); }; -typedef LocApiBase* (getLocApi_t)(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask, +typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase *context); } // namespace loc_core diff --git a/gps/core/LocContext.cpp b/gps/core/LocContext.cpp new file mode 100644 index 0000000..18d3f2d --- /dev/null +++ b/gps/core/LocContext.cpp @@ -0,0 +1,98 @@ +/* Copyright (c) 2011-2014, 2016-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_Ctx" + +#include +#include +#include +#include +#include +#include + +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(LocThread::tCreate tCreator, + const char* name, bool joinable) +{ + if (NULL == mMsgTask) { + mMsgTask = new MsgTask(tCreator, name, joinable); + } + return mMsgTask; +} + +inline +const MsgTask* LocContext::getMsgTask(const char* name, bool joinable) { + return getMsgTask((LocThread::tCreate)NULL, name, joinable); +} + +ContextBase* LocContext::getLocContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) +{ + 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(tCreator, name, joinable); + mContext = new LocContext(msgTask); + } + pthread_mutex_unlock(&LocContext::mGetLocContextMutex); + + if (firstMsg) { + mContext->sendMsg(firstMsg); + } + + 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..fb7d009 --- /dev/null +++ b/gps/core/LocContext.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2011-2014, 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 __LOC_CONTEXT__ +#define __LOC_CONTEXT__ + +#include +#include +#include +#include + +namespace loc_core { + +class LocContext : public ContextBase { + static const MsgTask* mMsgTask; + static ContextBase* mContext; + static const MsgTask* getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable = true); + static const MsgTask* getMsgTask(const char* name, bool joinable = true); + 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(LocThread::tCreate tCreator, LocMsg* firstMsg, + const char* name, bool joinable = true); + inline static ContextBase* getLocContext(const char* name, bool joinable = true) { + return getLocContext(NULL, NULL, name, joinable); + } + + static void injectFeatureConfig(ContextBase *context); +}; + +} + +#endif //__LOC_CONTEXT__ diff --git a/gps/core/LocDualContext.cpp b/gps/core/LocDualContext.cpp deleted file mode 100644 index 180d9dc..0000000 --- a/gps/core/LocDualContext.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (c) 2011-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. - * - */ -#define LOG_NDEBUG 0 -#define LOG_TAG "LocSvc_DualCtx" - -#include -#include -#include -#include -#include -#include - -namespace loc_core { - -// nothing exclude for foreground -const LOC_API_ADAPTER_EVENT_MASK_T -LocDualContext::mFgExclMask = 0; -// excluded events for background clients -const LOC_API_ADAPTER_EVENT_MASK_T -LocDualContext::mBgExclMask = - (LOC_API_ADAPTER_BIT_SATELLITE_REPORT | - LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | - LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT | - LOC_API_ADAPTER_BIT_IOCTL_REPORT | - LOC_API_ADAPTER_BIT_STATUS_REPORT | - LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT | - LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT); - -const MsgTask* LocDualContext::mMsgTask = NULL; -ContextBase* LocDualContext::mFgContext = NULL; -ContextBase* LocDualContext::mBgContext = NULL; -ContextBase* LocDualContext::mInjectContext = NULL; -// the name must be shorter than 15 chars -const char* LocDualContext::mLocationHalName = "Loc_hal_worker"; -#ifndef USE_GLIB -const char* LocDualContext::mLBSLibName = "liblbs_core.so"; -#else -const char* LocDualContext::mLBSLibName = "liblbs_core.so.1"; -#endif - -pthread_mutex_t LocDualContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; - -const MsgTask* LocDualContext::getMsgTask(LocThread::tCreate tCreator, - const char* name, bool joinable) -{ - if (NULL == mMsgTask) { - mMsgTask = new MsgTask(tCreator, name, joinable); - } - return mMsgTask; -} - -inline -const MsgTask* LocDualContext::getMsgTask(const char* name, bool joinable) { - return getMsgTask((LocThread::tCreate)NULL, name, joinable); -} - -ContextBase* LocDualContext::getLocFgContext(LocThread::tCreate tCreator, - LocMsg* firstMsg, const char* name, bool joinable) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); - if (NULL == mFgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); - mFgContext = new LocDualContext(msgTask, - mFgExclMask); - } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__); - mInjectContext = mFgContext; - injectFeatureConfig(mInjectContext); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - - if (firstMsg) { - mFgContext->sendMsg(firstMsg); - } - - return mFgContext; -} - -ContextBase* LocDualContext::getLocBgContext(LocThread::tCreate tCreator, - LocMsg* firstMsg, const char* name, bool joinable) -{ - pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); - LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); - if (NULL == mBgContext) { - LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); - const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); - mBgContext = new LocDualContext(msgTask, - mBgExclMask); - } - if(NULL == mInjectContext) { - LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__); - mInjectContext = mBgContext; - injectFeatureConfig(mInjectContext); - } - pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); - - if (firstMsg) { - mBgContext->sendMsg(firstMsg); - } - - return mBgContext; -} - -void LocDualContext :: injectFeatureConfig(ContextBase *curContext) -{ - LOC_LOGD("%s:%d]: Enter", __func__, __LINE__); - if(curContext == mInjectContext) { - LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config", - __func__, __LINE__, ((LocDualContext *)mInjectContext)->mLBSProxy); - ((LocDualContext *)mInjectContext)->mLBSProxy->injectFeatureConfig(curContext); - } - LOC_LOGD("%s:%d]: Exit", __func__, __LINE__); -} - -LocDualContext::LocDualContext(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask) : - ContextBase(msgTask, exMask, mLBSLibName) -{ -} - -} diff --git a/gps/core/LocDualContext.h b/gps/core/LocDualContext.h deleted file mode 100644 index 3b3ce2c..0000000 --- a/gps/core/LocDualContext.h +++ /dev/null @@ -1,76 +0,0 @@ -/* 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. - * - */ -#ifndef __LOC_ENG_CONTEXT__ -#define __LOC_ENG_CONTEXT__ - -#include -#include -#include -#include - -namespace loc_core { - -class LocDualContext : public ContextBase { - static const MsgTask* mMsgTask; - static ContextBase* mFgContext; - static ContextBase* mBgContext; - static ContextBase* mInjectContext; - static const MsgTask* getMsgTask(LocThread::tCreate tCreator, - const char* name, bool joinable = true); - static const MsgTask* getMsgTask(const char* name, bool joinable = true); - static pthread_mutex_t mGetLocContextMutex; - -protected: - LocDualContext(const MsgTask* msgTask, - LOC_API_ADAPTER_EVENT_MASK_T exMask); - inline virtual ~LocDualContext() {} - -public: - static const char* mLBSLibName; - static const LOC_API_ADAPTER_EVENT_MASK_T mFgExclMask; - static const LOC_API_ADAPTER_EVENT_MASK_T mBgExclMask; - static const char* mLocationHalName; - - static ContextBase* getLocFgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, - const char* name, bool joinable = true); - inline static ContextBase* getLocFgContext(const char* name, bool joinable = true) { - return getLocFgContext(NULL, NULL, name, joinable); - } - static ContextBase* getLocBgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, - const char* name, bool joinable = true); - inline static ContextBase* getLocBgContext(const char* name, bool joinable = true) { - return getLocBgContext(NULL, NULL, name, joinable); - } - - static void injectFeatureConfig(ContextBase *context); -}; - -} - -#endif //__LOC_ENG_CONTEXT__ diff --git a/gps/core/Makefile.am b/gps/core/Makefile.am deleted file mode 100644 index 77bc610..0000000 --- a/gps/core/Makefile.am +++ /dev/null @@ -1,66 +0,0 @@ -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 \ - LocDualContext.h \ - LBSProxyBase.h \ - UlpProxyBase.h \ - loc_core_log.h \ - LocAdapterProxyBase.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 \ - LocDualContext.cpp \ - loc_core_log.cpp \ - data-items/DataItemsFactoryProxy.cpp \ - SystemStatusOsObserver.cpp \ - SystemStatus.cpp - -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 - -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 index f4316ca..0624580 100644 --- a/gps/core/SystemStatus.cpp +++ b/gps/core/SystemStatus.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -126,6 +126,7 @@ public: uint32_t mBdsBpAmpQ; // x1C uint32_t mGalBpAmpI; // x1D uint32_t mGalBpAmpQ; // x1E + uint64_t mTimeUncNs; // x1F }; // parser @@ -166,6 +167,7 @@ private: eBdsBpAmpQ = 28, eGalBpAmpI = 29, eGalBpAmpQ = 30, + eTimeUncNs = 31, eMax }; SystemStatusPQWM1 mM1; @@ -201,6 +203,7 @@ public: 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) @@ -245,6 +248,9 @@ public: 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 @@ -376,16 +382,19 @@ public: 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, @@ -412,11 +421,13 @@ public: 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) @@ -425,6 +436,7 @@ public: 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()); @@ -505,21 +517,25 @@ public: 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, @@ -549,16 +565,19 @@ public: 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) @@ -567,6 +586,7 @@ public: 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); @@ -640,6 +660,7 @@ private: { eTalker = 0, eUtcTime = 1, + eMin = 2 + SV_ALL_NUM_MIN*3, eMax = 2 + SV_ALL_NUM*3 }; SystemStatusPQWP7 mP7; @@ -648,11 +669,18 @@ public: SystemStatusPQWP7parser(const char *str_in, uint32_t len_in) : SystemStatusNmeaBase(str_in, len_in) { - if (mField.size() < eMax) { + uint32_t svLimit = SV_ALL_NUM; + if (mField.size() < eMin) { LOC_LOGE("PQWP7parser - invalid size=%zu", mField.size()); return; } - for (uint32_t i=0; i #include #include +#include +#include #include #include #include @@ -42,20 +44,23 @@ #include -#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 GPS_NUM (32) -#define SBAS_NUM (32) -#define GLO_NUM (24) -#define QZSS_NUM (5) -#define BDS_NUM (37) -#define GAL_NUM (36) -#define SV_ALL_NUM (GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM) //=134 +#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 { @@ -66,15 +71,15 @@ namespace loc_core class SystemStatusItemBase { public: - timespec mUtcTime; // UTC timestamp when this info was last updated - timespec mUtcReported; // UTC timestamp when this info was reported + timespec mUtcTime; + timespec mUtcReported; static const uint32_t maxItem = 5; SystemStatusItemBase() { - struct timespec tv; - clock_gettime(CLOCK_MONOTONIC, &tv); + timeval tv; + gettimeofday(&tv, NULL); mUtcTime.tv_sec = tv.tv_sec; - mUtcTime.tv_nsec = tv.tv_nsec; + mUtcTime.tv_nsec = tv.tv_usec*1000ULL; mUtcReported = mUtcTime; }; virtual ~SystemStatusItemBase() {}; @@ -114,6 +119,7 @@ public: int32_t mClockFreqBiasUnc; int32_t mLeapSeconds; int32_t mLeapSecUnc; + uint64_t mTimeUncNs; inline SystemStatusTimeAndClock() : mGpsWeek(0), mGpsTowMs(0), @@ -123,7 +129,8 @@ public: mClockFreqBias(0), mClockFreqBiasUnc(0), mLeapSeconds(0), - mLeapSecUnc(0) {} + mLeapSecUnc(0), + mTimeUncNs(0ULL) {} inline SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea); bool equals(const SystemStatusTimeAndClock& peer); void dump(void); @@ -254,11 +261,13 @@ public: 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), @@ -266,11 +275,13 @@ public: mBdsXtraAge(0), mGalXtraAge(0), mQzssXtraAge(0), + mNavicXtraAge(0), mGpsXtraValid(0), mGloXtraValid(0), mBdsXtraValid(0ULL), mGalXtraValid(0ULL), - mQzssXtraValid(0) {} + mQzssXtraValid(0), + mNavicXtraValid(0) {} inline SystemStatusXtra(const SystemStatusPQWP3& nmea); bool equals(const SystemStatusXtra& peer); void dump(void); @@ -305,32 +316,38 @@ public: 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) {} + mQzssBadMask(0), + mNavicBadMask(0) {} inline SystemStatusSvHealth(const SystemStatusPQWP5& nmea); bool equals(const SystemStatusSvHealth& peer); void dump(void); @@ -467,7 +484,8 @@ public: std::string typeName="", string subTypeName="", bool connected=false, - bool roaming=false) : + bool roaming=false, + uint64_t networkHandle=NETWORK_HANDLE_UNKNOWN) : NetworkInfoDataItemBase( (NetworkType)type, type, @@ -475,7 +493,8 @@ public: subTypeName, connected && (!roaming), connected, - roaming), + roaming, + networkHandle), mSrcObjPtr(nullptr) {} inline SystemStatusNetworkInfo(const NetworkInfoDataItemBase& itemBase) : NetworkInfoDataItemBase(itemBase), @@ -483,20 +502,76 @@ public: mType = itemBase.getType(); } inline bool equals(const SystemStatusNetworkInfo& peer) { - return (mAllTypes == peer.mAllTypes); + for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) { + if (!(mAllNetworkHandles[i] == peer.mAllNetworkHandles[i])) { + return false; + } + } + return true; } inline virtual SystemStatusItemBase& collate(SystemStatusItemBase& curInfo) { uint64_t allTypes = (static_cast(curInfo)).mAllTypes; + uint64_t networkHandle = + (static_cast(curInfo)).mNetworkHandle; + int32_t type = (static_cast(curInfo)).mType; + // Replace current with cached table for now and then update + memcpy(mAllNetworkHandles, + (static_cast(curInfo)).getNetworkHandle(), + sizeof(mAllNetworkHandles)); 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) { - mAllTypes = (allTypes & (~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 == mAllNetworkHandles[lastValidIndex].networkType) { + typeCount++; + } + + if (mNetworkHandle == mAllNetworkHandles[lastValidIndex].networkHandle) { + deletedIndex = lastValidIndex; + typeCount--; + } + } + + 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; } @@ -713,8 +788,12 @@ public: BtDeviceScanDetailsDataItemBase() {} inline SystemStatusBtDeviceScanDetail(const BtDeviceScanDetailsDataItemBase& itemBase) : BtDeviceScanDetailsDataItemBase(itemBase) {} - inline bool equals(const SystemStatusBtDeviceScanDetail& /*peer*/) { - return true; + 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)); } }; @@ -726,8 +805,12 @@ public: BtLeDeviceScanDetailsDataItemBase() {} inline SystemStatusBtleDeviceScanDetail(const BtLeDeviceScanDetailsDataItemBase& itemBase) : BtLeDeviceScanDetailsDataItemBase(itemBase) {} - inline bool equals(const SystemStatusBtleDeviceScanDetail& /*peer*/) { - return true; + 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)); } }; @@ -822,7 +905,9 @@ public: 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 eventConnectionStatus(bool connected, int8_t type, + bool roaming, NetworkHandle networkHandle); + bool updatePowerConnectState(bool charging); }; } // namespace loc_core diff --git a/gps/core/SystemStatusOsObserver.cpp b/gps/core/SystemStatusOsObserver.cpp index 8127e86..0427380 100644 --- a/gps/core/SystemStatusOsObserver.cpp +++ b/gps/core/SystemStatusOsObserver.cpp @@ -97,6 +97,7 @@ void SystemStatusOsObserver::subscribe(const list& l, IDataItemObser list& l, IDataItemObserver* client, bool requestData) : mParent(parent), mClient(client), mDataItemSet(containerTransfer, unordered_set>(l)), + diItemlist(l), mToRequestData(requestData) {} void proc() const { @@ -107,16 +108,13 @@ void SystemStatusOsObserver::subscribe(const list& l, IDataItemObser mParent->sendCachedDataItems(mDataItemSet, mClient); // Send subscription set to framework - if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToSubscribe.empty()) { - LOC_LOGD("Subscribe Request sent to framework for the following"); - mParent->logMe(dataItemsToSubscribe); - + if (nullptr != mParent->mContext.mSubscriptionObj) { if (mToRequestData) { - mParent->mContext.mSubscriptionObj->requestData( - containerTransfer, list>( - std::move(dataItemsToSubscribe)), - mParent); - } else { + 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, list>( std::move(dataItemsToSubscribe)), @@ -127,6 +125,7 @@ void SystemStatusOsObserver::subscribe(const list& l, IDataItemObser mutable SystemStatusOsObserver* mParent; IDataItemObserver* mClient; const unordered_set mDataItemSet; + const list diItemlist; bool mToRequestData; }; @@ -405,7 +404,8 @@ void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut) DataItemId mDataItemId; int mTimeOut; }; - mContext.mMsgTask->sendMsg(new (nothrow) HandleTurnOnMsg(this, dit, timeOut)); + mContext.mMsgTask->sendMsg( + new (nothrow) HandleTurnOnMsg(mContext.mFrameworkActionReqObj, dit, timeOut)); } else { // Found in map, update reference count diff --git a/gps/core/UlpProxyBase.h b/gps/core/UlpProxyBase.h deleted file mode 100644 index 8863b66..0000000 --- a/gps/core/UlpProxyBase.h +++ /dev/null @@ -1,124 +0,0 @@ -/* 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 ULP_PROXY_BASE_H -#define ULP_PROXY_BASE_H - -#include -#include - -namespace loc_core { - -class LocAdapterBase; - -class UlpProxyBase { -public: - LocPosMode mPosMode; - bool mFixSet; - inline UlpProxyBase() { - mPosMode.mode = LOC_POSITION_MODE_INVALID; - mFixSet = false; - } - inline virtual ~UlpProxyBase() {} - inline virtual bool sendStartFix() { mFixSet = true; return false; } - inline virtual bool sendStopFix() { mFixSet = false; return false; } - inline virtual bool sendFixMode(LocPosMode ¶ms) { - mPosMode = params; - return false; - } - - inline virtual bool reportPosition(const UlpLocation &location, - const GpsLocationExtended &locationExtended, - enum loc_sess_status status, - LocPosTechMask loc_technology_mask) { - (void)location; - (void)locationExtended; - (void)status; - (void)loc_technology_mask; - return false; - } - inline virtual bool reportSv(const GnssSvNotification& svNotify) { - (void)svNotify; - return false; - } - inline virtual bool reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet) { - (void)svMeasurementSet; - return false; - } - - inline virtual bool reportSvPolynomial(GnssSvPolynomial &svPolynomial) - { - (void)svPolynomial; - return false; - } - inline virtual bool reportStatus(LocGpsStatusValue status) { - - (void)status; - return false; - } - inline virtual void setAdapter(LocAdapterBase* adapter) { - - (void)adapter; - } - inline virtual void setCapabilities(unsigned long capabilities) { - - (void)capabilities; - } - inline virtual bool reportBatchingSession(const LocationOptions& options, bool active) - { - (void)options; - (void)active; - return false; - } - inline virtual bool reportPositions(const UlpLocation* ulpLocations, - const GpsLocationExtended* extendedLocations, - const uint32_t* techMasks, - const size_t count) - { - (void)ulpLocations; - (void)extendedLocations; - (void)techMasks; - (void)count; - return false; - } - inline virtual bool reportDeleteAidingData(LocGpsAidingData aidingData) - { - (void)aidingData; - return false; - } - inline virtual bool reportNmea(const char* nmea, int length) - { - (void)nmea; - (void)length; - return false; - } -}; - -} // namespace loc_core - -#endif // ULP_PROXY_BASE_H diff --git a/gps/core/configure.ac b/gps/core/configure.ac deleted file mode 100644 index ea0a128..0000000 --- a/gps/core/configure.ac +++ /dev/null @@ -1,82 +0,0 @@ -# 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]) -# 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_CONFIG_FILES([ \ - Makefile \ - loc-core.pc \ - ]) - -AC_OUTPUT diff --git a/gps/core/data-items/DataItemConcreteTypesBase.h b/gps/core/data-items/DataItemConcreteTypesBase.h index bcb8d72..c32d65d 100644 --- a/gps/core/data-items/DataItemConcreteTypesBase.h +++ b/gps/core/data-items/DataItemConcreteTypesBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-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 @@ -32,8 +32,11 @@ #include #include +#include #include #include +#include +#include #define MAC_ADDRESS_LENGTH 6 // MAC address length in bytes @@ -41,10 +44,68 @@ #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): @@ -221,21 +282,9 @@ protected: class NetworkInfoDataItemBase : public IDataItemCore { public: - enum NetworkType { - TYPE_MOBILE, - TYPE_WIFI, - TYPE_ETHERNET, - TYPE_BLUETOOTH, - TYPE_MMS, - TYPE_SUPL, - TYPE_DUN, - TYPE_HIPRI, - TYPE_WIMAX, - TYPE_UNKNOWN, - }; NetworkInfoDataItemBase( NetworkType initialType, int32_t type, string typeName, string subTypeName, - bool available, bool connected, bool roaming ): + bool available, bool connected, bool roaming, uint64_t networkHandle ): mAllTypes(typeToAllTypes(initialType)), mType(type), mTypeName(typeName), @@ -243,7 +292,11 @@ public: mAvailable(available), mConnected(connected), mRoaming(roaming), - mId(NETWORKINFO_DATA_ITEM_ID) {} + mNetworkHandle(networkHandle), + mId(NETWORKINFO_DATA_ITEM_ID) { + mAllNetworkHandles[0].networkHandle = networkHandle; + mAllNetworkHandles[0].networkType = initialType; + } virtual ~NetworkInfoDataItemBase() {} inline virtual DataItemId getId() { return mId; } virtual void stringify(string& /*valueStr*/) {} @@ -252,6 +305,9 @@ public: return (NetworkType)mType; } inline uint64_t getAllTypes() { return mAllTypes; } + inline NetworkInfoType* getNetworkHandle() { + return &mAllNetworkHandles[0]; + } // Data members uint64_t mAllTypes; int32_t mType; @@ -260,6 +316,8 @@ public: bool mAvailable; bool mConnected; bool mRoaming; + NetworkInfoType mAllNetworkHandles[MAX_NETWORK_HANDLES]; + uint64_t mNetworkHandle; protected: DataItemId mId; inline uint64_t typeToAllTypes(NetworkType type) { diff --git a/gps/core/loc-core.pc.in b/gps/core/loc-core.pc.in deleted file mode 100644 index 76b514c..0000000 --- a/gps/core/loc-core.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -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 index 67d68f0..ddf18ec 100644 --- a/gps/core/loc_core_log.cpp +++ b/gps/core/loc_core_log.cpp @@ -39,14 +39,17 @@ 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", + "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); + provider, + powerMode, + timeBetweenMeasurements); } /* GPS status names */ diff --git a/gps/core/observer/IOsObserver.h b/gps/core/observer/IOsObserver.h index 40d7671..f661828 100644 --- a/gps/core/observer/IOsObserver.h +++ b/gps/core/observer/IOsObserver.h @@ -91,8 +91,8 @@ public: inline virtual void turnOn (DataItemId /*dit*/, int /*timeOut*/){} inline virtual void turnOff (DataItemId /*dit*/) {} #ifdef USE_GLIB - inline virtual bool connectBackhaul() {} - inline virtual bool disconnectBackhaul() {} + inline virtual bool connectBackhaul() { return false; } + inline virtual bool disconnectBackhaul() { return false; } #endif /** 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/gps.conf b/gps/etc/gps.conf new file mode 100644 index 0000000..f1d2ece --- /dev/null +++ b/gps/etc/gps.conf @@ -0,0 +1,306 @@ +#Version check for XTRA +#DISABLE = 0 +#AUTO = 1 +#XTRA2 = 2 +#XTRA3 = 3 +XTRA_VERSION_CHECK=0 + +# Error Estimate +# _SET = 1 +# _CLEAR = 0 +ERR_ESTIMATE=0 + +#NTP server +NTP_SERVER=time.izatcloud.net +#Asia +# NTP_SERVER=asia.pool.ntp.org +#Europe +# NTP_SERVER=europe.pool.ntp.org +#North America +# NTP_SERVER=north-america.pool.ntp.org +#XTRA CA path +XTRA_CA_PATH=/usr/lib/ssl/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=1 + +# supl version 1.0 +SUPL_VER=0x20000 + +# 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=3 + +# 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=70 + +################################ +##### AGPS server settings ##### +################################ + +# FOR SUPL SUPPORT, set the following +# SUPL_HOST=supl.host.com or IP +# SUPL_PORT=1234 +SUPL_HOST=supl.google.com +SUPL_PORT=7275 + +# 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 +#################################### +# 0: Enable RRLP on LTE(Default) +# 1: Enable LPP_User_Plane on LTE +# 2: Enable LPP_Control_Plane +# 3: Enable both LPP_User_Plane and LPP_Control_Plane +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 +# 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 + +################################################## +# QDR engine availability status +################################################## +# 0 : NO QDR (default) +# 1 : QDR enabled +# This settings enables QDR Configuration for +# automotive use case, if enabled then +# DR_AP_Service needs to be enabled in izat.conf +#EXTERNAL_DR_ENABLED = 0 + +##################################### +# 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 +# This setting use to select between QTI GNSS +# and QCSR SS5 hardware receiver. +# By default QTI GNSS receiver is enabled. +# GNSS_DEPLOYMENT = 0 diff --git a/gps/etc/izat.conf b/gps/etc/izat.conf new file mode 100644 index 0000000..27d3170 --- /dev/null +++ b/gps/etc/izat.conf @@ -0,0 +1,247 @@ +######################################### +# 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 = 4 +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) +GTP_MODE=DISABLED + +#GTP_WAA valid modes: +# DISABLED +# BASIC +GTP_WAA=DISABLED + +#SAP valid modes: +# DISABLED +# BASIC +# PREMIUM +# MODEM_DEFAULT +SAP=MODEM_DEFAULT + +#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 + +#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 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=ENABLED +PROCESS_GROUPS=gps wifi inet oem_2901 +PREMIUM_FEATURE=0 +IZAT_FEATURE_MASK=0xf303 +PLATFORMS=all +BASEBAND=all +HARDWARE_TYPE=all +VENDOR_ENHANCED_PROCESS=0 + +PROCESS_NAME=xtwifi-inet-agent +PROCESS_ARGUMENT= +PROCESS_STATE=ENABLED +PROCESS_GROUPS=inet gps +PREMIUM_FEATURE=1 +IZAT_FEATURE_MASK=0xc03 +PLATFORMS=all +BASEBAND=all +HARDWARE_TYPE=all +VENDOR_ENHANCED_PROCESS=1 + +PROCESS_NAME=xtwifi-client +PROCESS_ARGUMENT= +PROCESS_STATE=ENABLED +PROCESS_GROUPS=wifi inet gps system oem_2904 +PREMIUM_FEATURE=1 +IZAT_FEATURE_MASK=0xd03 +PLATFORMS=all +BASEBAND=all +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 +BASEBAND=all +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 +BASEBAND=all +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 +BASEBAND=all +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 oem_2901 +PREMIUM_FEATURE=0 +IZAT_FEATURE_MASK=0 +PLATFORMS=all +BASEBAND=all +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..5006b59 --- /dev/null +++ b/gps/etc/lowi.conf @@ -0,0 +1,27 @@ +#*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====* +# +# LOWI Config file +# +# 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 = 3 +LOWI_USE_LOWI_LP = 0 + diff --git a/gps/etc/sap.conf b/gps/etc/sap.conf new file mode 100644 index 0000000..0f71794 --- /dev/null +++ b/gps/etc/sap.conf @@ -0,0 +1,161 @@ +################################ +# 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= + +# 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=2 + +# 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 + +################################################ +# 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=100 + +#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=100 + +#Vehicle Gear batching value, it can either accept time in milli seconds or sample count +#VN_GEAR_CFG_BATCH_VALUE=100 + +#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 + +#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/xtwifi.conf b/gps/etc/xtwifi.conf new file mode 100644 index 0000000..5d7df9e --- /dev/null +++ b/gps/etc/xtwifi.conf @@ -0,0 +1,78 @@ +#GTP AP Project client core config file +# +#GENERAL DESCRIPTION +#This is used by client core +# +#Copyright (c) 2012-2014 Qualcomm Atheros, Inc. +#All Rights Reserved. +#Qualcomm Atheros Confidential and Proprietary. +# +#Copyright (c) 2017 Qualcomm Technologies, Inc. +#All Rights Reserved. +#Confidential and Proprietary - Qualcomm Technologies, Inc. + +############################################################################## +# non-IOT devices configuration items # +# For non-IOT devices, configure below configuration items # +# according to the app note: 80-NK218-1 and remove the configuration items # +# in section of "IOT devices configuration items". # +############################################################################## + +# ASN URI v2 to be used by some GTP AP modules that +# need to run with ASN URI v2 protocol. +XT_SERVER_ROOT_URL = https://gtp1.izatcloud.net:443/uds/v2 + +# ASN URI v3 to be used by GTP AP modules that +# can support ASN URI v3 protocol. +XT_SERVER_ROOT_URL_V3 = https://gtp1.izatcloud.net:443/uds/v3 + +# size, in bytes, of the cache on device +SIZE_BYTE_TOTAL_CACHE = 5000000 + +############################################################################## +# IOT devices configuration items # +# For IOT devices, configure below configuration items # +# according to the app note and remove the configuration items in section of # +# "non-IOT devices configuration items". # +############################################################################## + +# ASN URI v3 to be used by GTP AP modules that +# can support ASN URI v3 protocol. +# XT_SERVER_ROOT_URL_V3 = https://gtpma1.izatcloud.net:443/uds/v3 + +# 3: Wi-Fi APDB injection via Izat SDK. GTP server is not accessed +# for any GTP requests, instead notification is sent to Izat SDK. +# WiFi crowdsourcing module is disabled. +# 4: Wi-Fi APDB injection via Izat SDK. GTP server is not accessed +# for any GTP requests, instead notification is sent to Izat SDK. +# WiFi crowdsourcing module is active, also accessed via Izat SDK. +# GTP_AP_MODE = 4 + +# 1: MP cell features relies on GTP AP for either download or upload +# 0: MP cell features does not rely on GTP AP +# GTP_AP_NEEDED_BY_MP_CELL = 1 + +############################################################################## +# Configuration items applicable to all devices # +############################################################################## + +# Log verbosity control for most of the GTP WiFi system, including native and +# Java componenets +# OFF = 0, ERROR = 1, WARNING = 2, INFO = 3, DEBUG = 4, VERBOSE = 5, ALL = 100 +DEBUG_GLOBAL_LOG_LEVEL = 2 + +# this is used at the server side to distinguish uploads from different maker/model +# default "Qualcomm" +OEM_ID_IN_REQUEST_TO_SERVER = "Qualcomm" + +# this is used at the server side to distinguish uploads from different maker/model +# default "UNKNOWN" +MODEL_ID_IN_REQUEST_TO_SERVER = "UNKNOWN" + +############################################################################## +# Qualcomm Network Location Provider config # +############################################################################## + +# Accuracy Threshold for NLP position. Position exceeds thsi threshold will be filtered out. +# Default is 25000 meters. +LARGE_ACCURACY_THRESHOLD_TO_FILTER_NLP_POSITION = 25000 diff --git a/gps/geofence/Android.mk b/gps/geofence/Android.mk new file mode 100644 index 0000000..133d408 --- /dev/null +++ b/gps/geofence/Android.mk @@ -0,0 +1,38 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libgeofencing +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_TAGS := optional + +LOCAL_SRC_FILES:= \ + GeofenceAdapter.cpp \ + location_geofence.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libgps.utils \ + liblog \ + libloc_core + +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + +LOCAL_PRELINK_MODULE := false +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID +endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE + diff --git a/gps/geofence/GeofenceAdapter.cpp b/gps/geofence/GeofenceAdapter.cpp new file mode 100644 index 0000000..e299589 --- /dev/null +++ b/gps/geofence/GeofenceAdapter.cpp @@ -0,0 +1,870 @@ +/* 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. + * + */ +#define LOG_TAG "LocSvc_GeofenceAdapter" + +#include +#include "loc_log.h" +#include +#include + +using namespace loc_core; + +GeofenceAdapter::GeofenceAdapter() : + LocAdapterBase(0, + LocContext::getLocContext( + NULL, + NULL, + LocContext::mLocationHalName, + false), + 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(*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(*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 +#include +#include +#include + +using namespace loc_core; + +#define COPY_IF_NOT_NULL(dest, src, len) do { \ + if (NULL!=dest && NULL!=src) { \ + for (size_t i=0; i GeofencesMap; //map of hwId to GeofenceObject +typedef std::map 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/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 index 6ce0c34..9255f88 100644 --- a/gps/gnss/Agps.cpp +++ b/gps/gnss/Agps.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* 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 @@ -26,13 +26,14 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ - +#define LOG_NDEBUG 0 #define LOG_TAG "LocSvc_Agps" #include #include #include #include +#include /* -------------------------------------------------------------------- * AGPS State Machine Methods @@ -77,16 +78,8 @@ void AgpsStateMachine::processAgpsEventSubscribe(){ /* Add subscriber to list * No notifications until we get RSRC_GRANTED */ addSubscriber(mCurrentSubscriber); - - /* Send data request - * The if condition below is added so that if the data call setup - * fails for DS State Machine, we want to retry in released state. - * for Agps State Machine, sendRsrcRequest() will always return - * success. */ - if (requestOrReleaseDataConn(true) == 0) { - // If data request successful, move to pending state - transitionState(AGPS_STATE_PENDING); - } + requestOrReleaseDataConn(true); + transitionState(AGPS_STATE_PENDING); break; case AGPS_STATE_PENDING: @@ -293,24 +286,25 @@ void AgpsStateMachine::processAgpsEventDenied(){ * bool request : * true = Request data connection * false = Release data connection */ -int AgpsStateMachine::requestOrReleaseDataConn(bool request){ +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"); + 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"); + LOC_LOGD("AGPS Data Conn Release mAgpsType=%d mApnTypeMask=0x%X", + mAgpsType, mApnTypeMask); nifRequest.status = LOC_GPS_RELEASE_AGPS_DATA_CONN; } - mAgpsManager->mFrameworkStatusV4Cb(nifRequest); - return 0; + mFrameworkStatusV4Cb(nifRequest); } void AgpsStateMachine::notifyAllSubscribers( @@ -360,14 +354,14 @@ void AgpsStateMachine::notifyEventToSubscriber( case AGPS_EVENT_GRANTED: mAgpsManager->mAtlOpenStatusCb( - subscriberToNotify->mConnHandle, 1, getAPN(), - getBearer(), mAgpsType); + subscriberToNotify->mConnHandle, 1, getAPN(), getAPNLen(), + getBearer(), mAgpsType, mApnTypeMask); break; case AGPS_EVENT_DENIED: mAgpsManager->mAtlOpenStatusCb( - subscriberToNotify->mConnHandle, 0, getAPN(), - getBearer(), mAgpsType); + subscriberToNotify->mConnHandle, 0, getAPN(), getAPNLen(), + getBearer(), mAgpsType, mApnTypeMask); break; case AGPS_EVENT_UNSUBSCRIBE: @@ -451,15 +445,14 @@ void AgpsStateMachine::setAPN(char* apn, unsigned int len){ if (NULL != mAPN) { delete mAPN; + mAPN = NULL; } - if (apn == NULL || len <= 0) { + 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; - } - - if (NULL != apn) { + } else { mAPN = new char[len+1]; if (NULL != mAPN) { memcpy(mAPN, apn, len); @@ -512,195 +505,13 @@ void AgpsStateMachine::dropAllSubscribers(){ } } -/* -------------------------------------------------------------------- - * DS State Machine Methods - * -------------------------------------------------------------------*/ -const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4; -const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500; - -/* Overridden method - * DS SM needs to handle one scenario differently */ -void DSStateMachine::processAgpsEvent(AgpsEvent event) { - - LOC_LOGD("DSStateMachine::processAgpsEvent() %d", event); - - /* DS Client call setup APIs don't return failure/closure separately. - * Hence we receive RELEASED event in both cases. - * If we are in pending, we should consider RELEASED as DENIED */ - if (event == AGPS_EVENT_RELEASED && mState == AGPS_STATE_PENDING) { - - LOC_LOGD("Translating RELEASED to DENIED event"); - event = AGPS_EVENT_DENIED; - } - - /* Redirect process to base class */ - AgpsStateMachine::processAgpsEvent(event); -} - -/* Timer Callback - * For the retry timer started in case of DS Client call setup failure */ -void delay_callback(void *callbackData, int result) -{ - LOC_LOGD("delay_callback(): cbData %p", callbackData); - - (void)result; - - if (callbackData == NULL) { - LOC_LOGE("delay_callback(): NULL argument received !"); - return; - } - DSStateMachine* dsStateMachine = (DSStateMachine *)callbackData; - dsStateMachine->retryCallback(); -} - -/* Invoked from Timer Callback - * For the retry timer started in case of DS Client call setup failure */ -void DSStateMachine :: retryCallback() -{ - LOC_LOGD("DSStateMachine::retryCallback()"); - - /* Request SUPL ES - * There must be at least one active subscriber in list */ - AgpsSubscriber* subscriber = getFirstSubscriber(false); - if (subscriber == NULL) { - - LOC_LOGE("No active subscriber for DS Client call setup"); - return; - } - - /* Send message to retry */ - mAgpsManager->mSendMsgToAdapterQueueFn( - new AgpsMsgRequestATL( - mAgpsManager, subscriber->mConnHandle, - LOC_AGPS_TYPE_SUPL_ES)); -} - -/* Overridden method - * Request or Release data connection - * bool request : - * true = Request data connection - * false = Release data connection */ -int DSStateMachine::requestOrReleaseDataConn(bool request){ - - LOC_LOGD("DSStateMachine::requestOrReleaseDataConn(): " - "request %d", request); - - /* Release data connection required ? */ - if (!request && mAgpsManager->mDSClientStopDataCallFn) { - - mAgpsManager->mDSClientStopDataCallFn(); - LOC_LOGD("DS Client release data call request sent !"); - return 0; - } - - /* Setup data connection request - * There must be at least one active subscriber in list */ - AgpsSubscriber* subscriber = getFirstSubscriber(false); - if (subscriber == NULL) { - - LOC_LOGE("No active subscriber for DS Client call setup"); - return -1; - } - - /* DS Client Fn registered ? */ - if (!mAgpsManager->mDSClientOpenAndStartDataCallFn) { - - LOC_LOGE("DS Client start fn not registered, fallback to SUPL ATL"); - notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false); - return -1; - } - - /* Setup the call */ - int ret = mAgpsManager->mDSClientOpenAndStartDataCallFn(); - - /* Check if data call start failed */ - switch (ret) { - - case LOC_API_ADAPTER_ERR_ENGINE_BUSY: - LOC_LOGE("DS Client open call failed, err: %d", ret); - mRetries++; - if (mRetries > MAX_START_DATA_CALL_RETRIES) { - - LOC_LOGE("DS Client call retries exhausted, " - "falling back to normal SUPL ATL"); - notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false); - } - /* Retry DS Client call setup after some delay */ - else if(loc_timer_start( - DATA_CALL_RETRY_DELAY_MSEC, delay_callback, this)) { - LOC_LOGE("Error: Could not start delay thread\n"); - return -1; - } - break; - - case LOC_API_ADAPTER_ERR_UNSUPPORTED: - LOC_LOGE("No emergency profile found. Fall back to normal SUPL ATL"); - notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false); - break; - - case LOC_API_ADAPTER_ERR_SUCCESS: - LOC_LOGD("Request to start data call sent"); - break; - - default: - LOC_LOGE("Unrecognized return value: %d", ret); - } - - return ret; -} - -void DSStateMachine::notifyEventToSubscriber( - AgpsEvent event, AgpsSubscriber* subscriberToNotify, - bool deleteSubscriberPostNotify) { - - LOC_LOGD("DSStateMachine::notifyEventToSubscriber(): " - "SM %p, Event %d Subscriber %p Delete %d", - this, event, subscriberToNotify, deleteSubscriberPostNotify); - - switch (event) { - - case AGPS_EVENT_GRANTED: - mAgpsManager->mAtlOpenStatusCb( - subscriberToNotify->mConnHandle, 1, NULL, - AGPS_APN_BEARER_INVALID, LOC_AGPS_TYPE_SUPL_ES); - break; - - case AGPS_EVENT_DENIED: - /* Now try with regular SUPL - * We need to send request via message queue */ - mRetries = 0; - mAgpsManager->mSendMsgToAdapterQueueFn( - new AgpsMsgRequestATL( - mAgpsManager, subscriberToNotify->mConnHandle, - LOC_AGPS_TYPE_SUPL)); - break; - - case AGPS_EVENT_UNSUBSCRIBE: - mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1); - break; - - case AGPS_EVENT_RELEASED: - mAgpsManager->mDSClientCloseDataCallFn(); - mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1); - break; - - default: - LOC_LOGE("Invalid event %d", event); - } - - /* Search this subscriber in list and delete */ - if (deleteSubscriberPostNotify) { - deleteSubscriber(subscriberToNotify); - } -} - /* -------------------------------------------------------------------- * Loc AGPS Manager Methods * -------------------------------------------------------------------*/ /* CREATE AGPS STATE MACHINES * Must be invoked in Msg Handler context */ -void AgpsManager::createAgpsStateMachines() { +void AgpsManager::createAgpsStateMachines(const AgpsCbInfo& cbInfo) { LOC_LOGD("AgpsManager::createAgpsStateMachines"); @@ -708,31 +519,18 @@ void AgpsManager::createAgpsStateMachines() { ((loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA) || (loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB)); - if (NULL == mInternetNif) { + 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) { + 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); } - if (NULL == mDsNif && - loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { - - if(!mDSClientInitFn){ - - LOC_LOGE("DS Client Init Fn not registered !"); - return; - } - if (mDSClientInitFn(false) != 0) { - - LOC_LOGE("Failed to init data service client"); - return; - } - mDsNif = new DSStateMachine(this); - LOC_LOGD("DS NIF: %p", mDsNif); - } } } @@ -744,21 +542,16 @@ AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType 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_SUPL_ES: - if (loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { - if (mDsNif == NULL) { - createAgpsStateMachines(); - } - return mDsNif; - } else { - return mAgnssNif; + case LOC_AGPS_TYPE_WWAN_ANY: + if (mInternetNif == NULL) { + LOC_LOGE("NULL Internet NIF !"); } - + return mInternetNif; default: return mInternetNif; } @@ -767,30 +560,38 @@ AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType agpsType) { return NULL; } -void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType){ +void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType, + LocApnTypeMask apnTypeMask){ - LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType %d", - connHandle, agpsType); + 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", agpsType); + LOC_LOGE("No AGPS State Machine for agpsType: %d apnTypeMask: 0x%X", + agpsType, apnTypeMask); mAtlOpenStatusCb( - connHandle, 0, NULL, AGPS_APN_BEARER_INVALID, agpsType); + 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); + AgpsSubscriber subscriber(connHandle, false, false, apnTypeMask); sm->setCurrentSubscriber(&subscriber); - - /* If DS State Machine, wait for close complete */ - if (agpsType == LOC_AGPS_TYPE_SUPL_ES) { - subscriber.mWaitForCloseComplete = true; - } - /* Send subscriber event */ sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE); } @@ -812,15 +613,9 @@ void AgpsManager::releaseATL(int connHandle){ (subscriber = mInternetNif->getSubscriber(connHandle)) != NULL) { sm = mInternetNif; } - else if (mDsNif && - (subscriber = mDsNif->getSubscriber(connHandle)) != NULL) { - sm = mDsNif; - } - if (sm == NULL) { LOC_LOGE("Subscriber with connHandle %d not found in any SM", connHandle); - mAtlCloseStatusCb(connHandle, 0); return; } @@ -829,24 +624,6 @@ void AgpsManager::releaseATL(int connHandle){ sm->processAgpsEvent(AGPS_EVENT_UNSUBSCRIBE); } -void AgpsManager::reportDataCallOpened(){ - - LOC_LOGD("AgpsManager::reportDataCallOpened"); - - if (mDsNif) { - mDsNif->processAgpsEvent(AGPS_EVENT_GRANTED); - } -} - -void AgpsManager::reportDataCallClosed(){ - - LOC_LOGD("AgpsManager::reportDataCallClosed"); - - if (mDsNif) { - mDsNif->processAgpsEvent(AGPS_EVENT_RELEASED); - } -} - void AgpsManager::reportAtlOpenSuccess( AGpsExtType agpsType, char* apnName, int apnLen, AGpsBearerType bearerType){ @@ -895,18 +672,4 @@ void AgpsManager::handleModemSSR(){ if (mInternetNif) { mInternetNif->dropAllSubscribers(); } - if (mDsNif) { - mDsNif->dropAllSubscribers(); - } - - // reinitialize DS client in SSR mode - if (loc_core::ContextBase::mGps_conf. - USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { - - mDSClientStopDataCallFn(); - mDSClientCloseDataCallFn(); - mDSClientReleaseFn(); - - mDSClientInitFn(true); - } } diff --git a/gps/gnss/Agps.h b/gps/gnss/Agps.h index 703a475..d559377 100644 --- a/gps/gnss/Agps.h +++ b/gps/gnss/Agps.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -40,18 +40,11 @@ /* ATL callback function pointers * Passed in by Adapter to AgpsManager */ typedef std::function AgpsAtlOpenStatusCb; + int handle, int isSuccess, char* apn, uint32_t apnLen, + AGpsBearerType bearerType, AGpsExtType agpsType, + LocApnTypeMask mask)> AgpsAtlOpenStatusCb; -typedef std::function AgpsAtlCloseStatusCb; - -/* DS Client control APIs - * Passed in by Adapter to AgpsManager */ -typedef std::function AgpsDSClientInitFn; -typedef std::function AgpsDSClientOpenAndStartDataCallFn; -typedef std::function AgpsDSClientStopDataCallFn; -typedef std::function AgpsDSClientCloseDataCallFn; -typedef std::function AgpsDSClientReleaseFn; +typedef std::function AgpsAtlCloseStatusCb; /* Post message to adapter's message queue */ typedef std::function SendMsgToAdapterMsgQueueFn; @@ -92,8 +85,6 @@ typedef enum { class AgpsSubscriber; class AgpsManager; class AgpsStateMachine; -class DSStateMachine; - /* SUBSCRIBER * Each Subscriber instance corresponds to one AGPS request, @@ -109,12 +100,15 @@ public: * inactive state. */ bool mWaitForCloseComplete; bool mIsInactive; + LocApnTypeMask mApnTypeMask; inline AgpsSubscriber( - int connHandle, bool waitForCloseComplete, bool isInactive) : + int connHandle, bool waitForCloseComplete, bool isInactive, + LocApnTypeMask apnTypeMask) : mConnHandle(connHandle), mWaitForCloseComplete(waitForCloseComplete), - mIsInactive(isInactive) {} + mIsInactive(isInactive), + mApnTypeMask(apnTypeMask) {} inline virtual ~AgpsSubscriber() {} inline virtual bool equals(const AgpsSubscriber *s) const @@ -122,7 +116,7 @@ public: inline virtual AgpsSubscriber* clone() { return new AgpsSubscriber( - mConnHandle, mWaitForCloseComplete, mIsInactive); } + mConnHandle, mWaitForCloseComplete, mIsInactive, mApnTypeMask); } }; /* AGPS STATE MACHINE */ @@ -143,6 +137,7 @@ protected: /* Current state for this state machine */ AgpsState mState; + AgnssStatusIpV4Cb mFrameworkStatusV4Cb; private: /* AGPS Type for this state machine LOC_AGPS_TYPE_ANY 0 @@ -150,6 +145,7 @@ private: 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; @@ -159,6 +155,7 @@ private: public: /* CONSTRUCTOR */ AgpsStateMachine(AgpsManager* agpsManager, AGpsExtType agpsType): + mFrameworkStatusV4Cb(NULL), mAgpsManager(agpsManager), mSubscriberList(), mCurrentSubscriber(NULL), mState(AGPS_STATE_RELEASED), mAgpsType(agpsType), mAPN(NULL), mAPNLen(0), @@ -169,12 +166,21 @@ public: /* 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); @@ -199,7 +205,7 @@ private: /* Send call setup request to framework * sendRsrcRequest(LOC_GPS_REQUEST_AGPS_DATA_CONN) * sendRsrcRequest(LOC_GPS_RELEASE_AGPS_DATA_CONN) */ - virtual int requestOrReleaseDataConn(bool request); + void requestOrReleaseDataConn(bool request); /* Individual event processing methods */ void processAgpsEventSubscribe(); @@ -227,91 +233,33 @@ private: void transitionState(AgpsState newState); }; -/* DS STATE MACHINE */ -class DSStateMachine : public AgpsStateMachine { - -private: - static const int MAX_START_DATA_CALL_RETRIES; - static const int DATA_CALL_RETRY_DELAY_MSEC; - - int mRetries; - -public: - /* CONSTRUCTOR */ - DSStateMachine(AgpsManager* agpsManager): - AgpsStateMachine(agpsManager, LOC_AGPS_TYPE_SUPL_ES), mRetries(0) {} - - /* Overridden method - * DS SM needs to handle one event differently */ - void processAgpsEvent(AgpsEvent event); - - /* Retry callback, used in case call failure */ - void retryCallback(); - -private: - /* Overridden method, different functionality for DS SM - * Send call setup request to framework - * sendRsrcRequest(LOC_GPS_REQUEST_AGPS_DATA_CONN) - * sendRsrcRequest(LOC_GPS_RELEASE_AGPS_DATA_CONN) */ - int requestOrReleaseDataConn(bool request); - - /* Overridden method, different functionality for DS SM */ - void notifyEventToSubscriber( - AgpsEvent event, AgpsSubscriber* subscriber, - bool deleteSubscriberPostNotify); -}; - /* LOC AGPS MANAGER */ class AgpsManager { friend class AgpsStateMachine; - friend class DSStateMachine; - public: /* CONSTRUCTOR */ AgpsManager(): - mFrameworkStatusV4Cb(NULL), mAtlOpenStatusCb(), mAtlCloseStatusCb(), - mDSClientInitFn(), mDSClientOpenAndStartDataCallFn(), - mDSClientStopDataCallFn(), mDSClientCloseDataCallFn(), mDSClientReleaseFn(), - mSendMsgToAdapterQueueFn(), - mAgnssNif(NULL), mInternetNif(NULL), mDsNif(NULL) {} + mAgnssNif(NULL), mInternetNif(NULL)/*, mDsNif(NULL)*/ {} /* Register callbacks */ inline void registerATLCallbacks(AgpsAtlOpenStatusCb atlOpenStatusCb, - AgpsAtlCloseStatusCb atlCloseStatusCb, - AgpsDSClientInitFn dsClientInitFn, - AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn, - AgpsDSClientStopDataCallFn dsClientStopDataCallFn, - AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn, - AgpsDSClientReleaseFn dsClientReleaseFn, - SendMsgToAdapterMsgQueueFn sendMsgToAdapterQueueFn) { + AgpsAtlCloseStatusCb atlCloseStatusCb) { mAtlOpenStatusCb = atlOpenStatusCb; mAtlCloseStatusCb = atlCloseStatusCb; - mDSClientInitFn = dsClientInitFn; - mDSClientOpenAndStartDataCallFn = dsClientOpenAndStartDataCallFn; - mDSClientStopDataCallFn = dsClientStopDataCallFn; - mDSClientCloseDataCallFn = dsClientCloseDataCallFn; - mDSClientReleaseFn = dsClientReleaseFn; - mSendMsgToAdapterQueueFn = sendMsgToAdapterQueueFn; } - inline void registerFrameworkStatusCallback(AgnssStatusIpV4Cb frameworkStatusV4Cb) { - mFrameworkStatusV4Cb = frameworkStatusV4Cb; - } + /* Check if AGPS client is registered */ + inline bool isRegistered() { return nullptr != mAgnssNif || nullptr != mInternetNif; } /* Create all AGPS state machines */ - void createAgpsStateMachines(); + void createAgpsStateMachines(const AgpsCbInfo& cbInfo); /* Process incoming ATL requests */ - void requestATL(int connHandle, AGpsExtType agpsType); + void requestATL(int connHandle, AGpsExtType agpsType, LocApnTypeMask apnTypeMask); void releaseATL(int connHandle); - - /* Process incoming DS Client data call events */ - void reportDataCallOpened(); - void reportDataCallClosed(); - /* Process incoming framework data call events */ void reportAtlOpenSuccess(AGpsExtType agpsType, char* apnName, int apnLen, AGpsBearerType bearerType); @@ -322,23 +270,11 @@ public: void handleModemSSR(); protected: - AgnssStatusIpV4Cb mFrameworkStatusV4Cb; AgpsAtlOpenStatusCb mAtlOpenStatusCb; AgpsAtlCloseStatusCb mAtlCloseStatusCb; - - AgpsDSClientInitFn mDSClientInitFn; - AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn; - AgpsDSClientStopDataCallFn mDSClientStopDataCallFn; - AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn; - AgpsDSClientReleaseFn mDSClientReleaseFn; - - SendMsgToAdapterMsgQueueFn mSendMsgToAdapterQueueFn; - AgpsStateMachine* mAgnssNif; AgpsStateMachine* mInternetNif; - AgpsStateMachine* mDsNif; - private: /* Fetch state machine for handling request ATL call */ AgpsStateMachine* getAgpsStateMachine(AGpsExtType agpsType); @@ -353,11 +289,12 @@ struct AgpsMsgRequestATL: public LocMsg { AgpsManager* mAgpsManager; int mConnHandle; AGpsExtType mAgpsType; + LocApnTypeMask mApnTypeMask; inline AgpsMsgRequestATL(AgpsManager* agpsManager, int connHandle, - AGpsExtType agpsType) : - LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle), mAgpsType( - agpsType) { + AGpsExtType agpsType, LocApnTypeMask apnTypeMask) : + LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle), + mAgpsType(agpsType), mApnTypeMask(apnTypeMask){ LOC_LOGV("AgpsMsgRequestATL"); } @@ -365,7 +302,7 @@ struct AgpsMsgRequestATL: public LocMsg { inline virtual void proc() const { LOC_LOGV("AgpsMsgRequestATL::proc()"); - mAgpsManager->requestATL(mConnHandle, mAgpsType); + mAgpsManager->requestATL(mConnHandle, mAgpsType, mApnTypeMask); } }; diff --git a/gps/gnss/Android.mk b/gps/gnss/Android.mk index d809bc2..c1b5944 100644 --- a/gps/gnss/Android.mk +++ b/gps/gnss/Android.mk @@ -6,6 +6,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libgnss +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_TAGS := optional diff --git a/gps/gnss/GnssAdapter.cpp b/gps/gnss/GnssAdapter.cpp index 751c148..980d489 100644 --- a/gps/gnss/GnssAdapter.cpp +++ b/gps/gnss/GnssAdapter.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -26,6 +26,7 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +#define LOG_NDEBUG 0 #define LOG_TAG "LocSvc_GnssAdapter" #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +49,8 @@ #include #define RAD2DEG (180.0 / M_PI) +#define PROCESS_NAME_ENGINE_SERVICE "engine-service" +#define MIN_TRACKING_INTERVAL (100) // 100 msec using namespace loc_core; @@ -60,30 +64,43 @@ static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userD GnssAdapter::GnssAdapter() : LocAdapterBase(0, - LocDualContext::getLocFgContext(NULL, + LocContext::getLocContext(NULL, NULL, - LocDualContext::mLocationHalName, - false)), - mUlpProxy(new UlpProxyBase()), - mUlpPositionMode(), + LocContext::mLocationHalName, + false), true, nullptr), + mEngHubProxy(new EngineHubProxyBase()), + mLocPositionMode(), mGnssSvIdUsedInPosition(), mGnssSvIdUsedInPosAvail(false), mControlCallbacks(), - mPowerVoteId(0), + mAfwControlId(0), mNmeaMask(0), + mGnssSvIdConfig(), + mGnssSvTypeConfig(), + mGnssSvTypeConfigCb(nullptr), mNiData(), mAgpsManager(), - mAgpsCbInfo(), mOdcpiRequestCb(nullptr), mOdcpiRequestActive(false), mOdcpiTimer(this), mOdcpiRequest(), mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), - mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask) + mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask), + mLocSystemInfo{}, + mBlockCPIInfo{}, + mNfwCb(NULL), + mPowerOn(false), + mAllowFlpNetworkFixes(0), + mGnssEnergyConsumedCb(nullptr), + mPowerStateCb(nullptr), + mIsE911Session(NULL), + mGnssMbSvIdUsedInPosition{}, + mGnssMbSvIdUsedInPosAvail(false), + mSupportNfwControl(true) { LOC_LOGD("%s]: Constructor %p", __func__, this); - mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID; + mLocPositionMode.mode = LOC_POSITION_MODE_INVALID; pthread_condattr_t condAttr; pthread_condattr_init(&condAttr); @@ -94,62 +111,22 @@ GnssAdapter::GnssAdapter() : /* Set ATL open/close callbacks */ AgpsAtlOpenStatusCb atlOpenStatusCb = - [this](int handle, int isSuccess, char* apn, - AGpsBearerType bearerType, AGpsExtType agpsType) { + [this](int handle, int isSuccess, char* apn, uint32_t apnLen, + AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) { mLocApi->atlOpenStatus( - handle, isSuccess, apn, bearerType, agpsType); + handle, isSuccess, apn, apnLen, bearerType, agpsType, mask); }; AgpsAtlCloseStatusCb atlCloseStatusCb = [this](int handle, int isSuccess) { mLocApi->atlCloseStatus(handle, isSuccess); }; - - /* Register DS Client APIs */ - AgpsDSClientInitFn dsClientInitFn = - [this](bool isDueToSSR) { - - return mLocApi->initDataServiceClient(isDueToSSR); - }; - - AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn = - [this] { - - return mLocApi->openAndStartDataCall(); - }; - - AgpsDSClientStopDataCallFn dsClientStopDataCallFn = - [this] { - - mLocApi->stopDataCall(); - }; - - AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn = - [this] { - - mLocApi->closeDataCall(); - }; - - AgpsDSClientReleaseFn dsClientReleaseFn = - [this] { - - mLocApi->releaseDataServiceClient(); - }; - - /* Send Msg function */ - SendMsgToAdapterMsgQueueFn sendMsgFn = - [this](LocMsg* msg) { - - sendMsg(msg); - }; - mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb, - dsClientInitFn, dsClientOpenAndStartDataCallFn, dsClientStopDataCallFn, - dsClientCloseDataCallFn, dsClientReleaseFn, sendMsgFn); + mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb); readConfigCommand(); - setConfigCommand(); initDefaultAgpsCommand(); + initEngHubProxyCommand(); } void @@ -172,10 +149,9 @@ GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbac } void -GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options) +GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions) { - LocPosMode locPosMode = {}; - switch (options.mode) { + switch (trackingOptions.mode) { case GNSS_SUPL_MODE_MSB: out.mode = LOC_POSITION_MODE_MS_BASED; break; @@ -187,36 +163,38 @@ GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options) break; } out.share_position = true; - out.min_interval = options.minInterval; + out.min_interval = trackingOptions.minInterval; + out.powerMode = trackingOptions.powerMode; + out.timeBetweenMeasurements = trackingOptions.tbm; } void -GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation, +GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, const LocPosTechMask techMask) { memset(&out, 0, sizeof(Location)); out.size = sizeof(Location); - if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) { + if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_LAT_LONG_BIT; - out.latitude = locGpsLocation.latitude; - out.longitude = locGpsLocation.longitude; + out.latitude = ulpLocation.gpsLocation.latitude; + out.longitude = ulpLocation.gpsLocation.longitude; } - if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) { + if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_ALTITUDE_BIT; - out.altitude = locGpsLocation.altitude; + out.altitude = ulpLocation.gpsLocation.altitude; } - if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) { + if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_SPEED_BIT; - out.speed = locGpsLocation.speed; + out.speed = ulpLocation.gpsLocation.speed; } - if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) { + if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_BEARING_BIT; - out.bearing = locGpsLocation.bearing; + out.bearing = ulpLocation.gpsLocation.bearing; } - if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) { + if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) { out.flags |= LOCATION_HAS_ACCURACY_BIT; - out.accuracy = locGpsLocation.accuracy; + out.accuracy = ulpLocation.gpsLocation.accuracy; } if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) { out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; @@ -230,7 +208,7 @@ GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; out.bearingAccuracy = locationExtended.bearing_unc; } - out.timestamp = locGpsLocation.timestamp; + out.timestamp = ulpLocation.gpsLocation.timestamp; if (LOC_POS_TECH_MASK_SATELLITE & techMask) { out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT; } @@ -243,6 +221,36 @@ GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation if (LOC_POS_TECH_MASK_SENSORS & techMask) { out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT; } + + if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) { + out.flags |= LOCATION_HAS_SPOOF_MASK; + out.spoofMask = ulpLocation.gpsLocation.spoof_mask; + } +} + +/* 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 @@ -254,7 +262,14 @@ GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT; out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel; } - if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) { + 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; @@ -316,40 +331,173 @@ GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, 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.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.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_TECH_MASK & locationExtended.flags) { + out.flags |= GNSS_LOCATION_INFO_POS_TECH_MASK_BIT; + out.posTechMask = locationExtended.tech_mask; + } + 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; + } + 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; + } + if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME; + out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc; + out.gnssSystemTime.u = locationExtended.gnssSystemTime.u; + } + if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL; + out.northVelocity = locationExtended.northVelocity; + } + if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL; + out.eastVelocity = locationExtended.eastVelocity; + } + if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL; + out.upVelocity = locationExtended.upVelocity; + } + if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC; + out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation; + } + if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC; + out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation; + } + if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) { + out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC; + out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation; + } -inline uint32_t -GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock) -{ - switch (gpsLock) { - case GNSS_CONFIG_GPS_LOCK_MO: - return 1; - case GNSS_CONFIG_GPS_LOCK_NI: - return 2; - case GNSS_CONFIG_GPS_LOCK_MO_AND_NI: - return 3; - case GNSS_CONFIG_GPS_LOCK_NONE: - default: - return 0; + // 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; } -} -inline GnssConfigGpsLock -GnssAdapter::convertGpsLock(const uint32_t gpsLock) -{ - switch (gpsLock) { - case 1: - return GNSS_CONFIG_GPS_LOCK_MO; - case 2: - return GNSS_CONFIG_GPS_LOCK_NI; - case 3: - return GNSS_CONFIG_GPS_LOCK_MO_AND_NI; - case 0: - default: - return GNSS_CONFIG_GPS_LOCK_NONE; + 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; } } + + inline uint32_t GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) { @@ -364,20 +512,6 @@ GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) } } -inline GnssConfigSuplVersion -GnssAdapter::convertSuplVersion(const uint32_t suplVersion) -{ - switch (suplVersion) { - case 0x00020000: - return GNSS_CONFIG_SUPL_VERSION_2_0_0; - case 0x00020002: - return GNSS_CONFIG_SUPL_VERSION_2_0_2; - case 0x00010000: - default: - return GNSS_CONFIG_SUPL_VERSION_1_0_0; - } -} - inline uint32_t GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile) { @@ -394,22 +528,6 @@ GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile) } } -inline GnssConfigLppProfile -GnssAdapter::convertLppProfile(const uint32_t lppProfile) -{ - switch (lppProfile) { - case 1: - return GNSS_CONFIG_LPP_PROFILE_USER_PLANE; - case 2: - return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; - case 3: - return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; - case 0: - default: - return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; - } -} - uint32_t GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask) { @@ -429,26 +547,6 @@ GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlane return mask; } -GnssConfigLppeControlPlaneMask -GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask) -{ - GnssConfigLppeControlPlaneMask mask = 0; - if ((1<<0) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT; - } - if ((1<<1) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT; - } - if ((1<<2) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT; - } - if ((1<<3) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT; - } - return mask; -} - - uint32_t GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask) { @@ -468,25 +566,6 @@ GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask) return mask; } -GnssConfigLppeUserPlaneMask -GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask) -{ - GnssConfigLppeUserPlaneMask mask = 0; - if ((1<<0) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT; - } - if ((1<<1) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT; - } - if ((1<<2) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT; - } - if ((1<<3) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT; - } - return mask; -} - uint32_t GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask) { @@ -543,27 +622,6 @@ GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask) return mask; } -bool -GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress) -{ - bool ret = true; - - struct hostent* hp; - hp = gethostbyname(hostAddress); - if (hp != NULL) { /* DNS OK */ - memcpy(inAddress, hp->h_addr_list[0], hp->h_length); - } else { - /* Try IP representation */ - if (inet_aton(hostAddress, inAddress) == 0) { - /* IP not valid */ - LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress); - ret = false; - } - } - - return ret; -} - void GnssAdapter::readConfigCommand() { @@ -578,9 +636,21 @@ GnssAdapter::readConfigCommand() mAdapter(adapter), mContext(context) {} inline virtual void proc() const { - // reads config into mContext->mGps_conf - mContext.readConfig(); - mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities()); + 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); + } } }; @@ -589,17 +659,14 @@ GnssAdapter::readConfigCommand() } } -LocationError -GnssAdapter::setSuplHostServer(const char* server, int port) +void +GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type) { - LocationError locErr = LOCATION_ERROR_SUCCESS; if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { char serverUrl[MAX_URL_LEN] = {}; int32_t length = -1; const char noHost[] = "NONE"; - locErr = LOCATION_ERROR_INVALID_PARAMETER; - if ((NULL == server) || (server[0] == 0) || (strncasecmp(noHost, server, sizeof(noHost)) == 0)) { serverUrl[0] = '\0'; @@ -607,94 +674,347 @@ GnssAdapter::setSuplHostServer(const char* server, int port) } else if (port > 0) { length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port); } - - if (length >= 0 && strncasecmp(getServerUrl().c_str(), - serverUrl, sizeof(serverUrl)) != 0) { - setServerUrl(serverUrl); - locErr = mLocApi->setServer(serverUrl, length); - if (locErr != LOCATION_ERROR_SUCCESS) { - LOC_LOGE("%s]:Error while setting SUPL_HOST server:%s", - __func__, serverUrl); + 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, server, LOC_MAX_PARAM_STRING); + ContextBase::mGps_conf.SUPL_PORT = port; + } else { + if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) { + getMoServerUrl().assign(serverUrl); + } } } } - return locErr; } void -GnssAdapter::setConfigCommand() +GnssAdapter::setConfig() { LOC_LOGD("%s]: ", __func__); - struct MsgSetConfig : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgSetConfig(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER)); - mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE)); - mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT); - } - mAdapter.setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST, - ContextBase::mGps_conf.SUPL_PORT); - mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE, - ContextBase::mSap_conf.SENSOR_PROVIDER); - mApi.setLPPeProtocolCp( - mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY)); - mApi.setLPPeProtocolUp( - mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY)); - - // 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 (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { - mask |= LOC_NMEA_MASK_DEBUG_V02; - } - if (mask != 0) { - mApi.setNMEATypes(mask); - } - mAdapter.mNmeaMask= mask; - - mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK); - if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID || - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) { - mApi.setSensorProperties( - ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID, - ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK, - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY); - } - mApi.setSensorPerfControlConfig( - ContextBase::mSap_conf.SENSOR_CONTROL_MODE, - ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, - ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, - ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, - ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC, - ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, - ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, - ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, - ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, - ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK); + // 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::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; + } + + if (gpsConf.AGPS_CONFIG_INJECT) { + 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.lppProfile = + mLocApi->convertLppProfile(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] () { + 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 (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { + mask |= LOC_NMEA_MASK_DEBUG_V02; + } + + if (mask != 0) { + mLocApi->setNMEATypesSync(mask); + } + + mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK); + + mLocApi->setConstrainedTuncMode( + gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1, + (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD, + gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET); + mLocApi->setPositionAssistedClockEstimatorMode( + gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED == 1); + + 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); + } )); + +} + +std::vector GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl, + const GnssConfig& gnssConfigRequested, + const GnssConfig& gnssConfigNeedEngineUpdate, size_t count) { + loc_gps_cfg_s gpsConf = ContextBase::mGps_conf; + size_t index = 0; + LocationError err = LOCATION_ERROR_SUCCESS; + std::vector 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 (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.lppProfile); + 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++; + } - sendMsg(new MsgSetConfig(*this, *mLocApi)); + 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++; + } + return errsList; } uint32_t* @@ -732,8 +1052,8 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) GnssAdapter& mAdapter; LocApiBase& mApi; GnssConfig mConfig; - uint32_t* mIds; size_t mCount; + uint32_t* mIds; inline MsgGnssUpdateConfig(GnssAdapter& adapter, LocApiBase& api, GnssConfig config, @@ -743,165 +1063,153 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) mAdapter(adapter), mApi(api), mConfig(config), - mIds(ids), - mCount(count) {} + mCount(count), + mIds(ids) {} + inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) : + MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig, + new uint32_t[obj.mCount], obj.mCount) { + if (mIds != nullptr) { + for (int i = 0; i < mCount; ++i) { + mIds[i] = obj.mIds[i]; + } + } + } inline virtual ~MsgGnssUpdateConfig() { delete[] mIds; } - inline virtual void proc() const { - LocationError* errs = new LocationError[mCount]; - LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t index = 0; - if (errs == nullptr) { - LOC_LOGE("%s] new allocation failed, fatal error.", __func__); + 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 sessionIds; + sessionIds.assign(mIds, mIds + mCount); + std::vector errs(mCount, LOCATION_ERROR_SUCCESS); + int index = 0; - if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { - uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock); + 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 (0 == mAdapter.getPowerVoteId()) { - err = mApi.setGpsLock(mConfig.gpsLock); - } - if (index < mCount) { - errs[index++] = err; + /* 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 (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { - uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion); - if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.SUPL_VER = newSuplVersion; - err = mApi.setSUPLVersion(mConfig.suplVersion); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index++] = err; - } + 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 (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) { - err = mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName, - mConfig.assistanceServer.port); - } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) { - if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - struct in_addr addr; - if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, - &addr)) { - LOC_LOGE("%s]: hostName %s cannot be resolved", - __func__, mConfig.assistanceServer.hostName); - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { - unsigned int ip = htonl(addr.s_addr); - err = mApi.setServer(ip, mConfig.assistanceServer.port, - LOC_AGPS_CDMA_PDE_SERVER); - } - } else { - err = LOCATION_ERROR_SUCCESS; - } + 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); - err = LOCATION_ERROR_INVALID_PARAMETER; - } - if (index < mCount) { - errs[index++] = err; + __func__, mConfig.assistanceServer.type); + errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER; + gnssConfigNeedEngineUpdate.flags &= + ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT); } + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { - uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile); - if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.LPP_PROFILE = newLppProfile; - err = mApi.setLPPConfig(mConfig.lppProfile); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index++] = err; - } + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { + uint32_t newLppProfile = mAdapter.convertLppProfile(gnssConfigRequested.lppProfile); + ContextBase::mGps_conf.LPP_PROFILE = newLppProfile; + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { uint32_t newLppeControlPlaneMask = - mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask); - if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) { - ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask; - err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index++] = err; - } + mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask); + ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask; + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { + if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { uint32_t newLppeUserPlaneMask = - mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask); - if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) { - ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask; - err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index++] = err; - } + mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask); + ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask; + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { + if (gnssConfigRequested.flags & + GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { uint32_t newAGloProtMask = - mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask); - if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask; - err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index++] = err; - } + mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask); + ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask; + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { - uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl); + 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; } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index++] = err; - } + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { - uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices); + 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; } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index++] = err; - } + index++; } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { - uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask); - if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) { - ContextBase::mGps_conf.SUPL_MODE = newSuplMode; - mAdapter.getUlpProxy()->setCapabilities( - ContextBase::getCarrierCapabilities()); - mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); - } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index++] = err; - } + 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++; } - mAdapter.reportResponse(index, errs, mIds); - delete[] errs; - } - }; + LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse( + *adapter.getContext(), + [&adapter, sessionIds, countOfConfigs] (std::vector errs) { + + std::vector ids(sessionIds); + adapter.reportResponse(countOfConfigs, errs.data(), ids.data()); + }); + + mApi.sendMsg(new LocApiMsg( + [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate, + countOfConfigs, configCollectiveResponse, errs] () { + std::vector errsList = adapter.gnssUpdateConfig("", + gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs); + + configCollectiveResponse->returnToSender(errsList); + })); + } + }; if (NULL != ids) { sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count)); @@ -912,6 +1220,584 @@ GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) return ids; } +void +GnssAdapter::gnssSvIdConfigUpdate(const std::vector& 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, + mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask, + mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask); + + // Now set required blacklisted SVs + mLocApi->setBlacklistSv(mGnssSvIdConfig); +} + +LocationError +GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector& 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, + mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask, + mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask); + + // Now set required blacklisted SVs + return mLocApi->setBlacklistSvSync(mGnssSvIdConfig); +} + +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), + mIds(ids), + mCount(count) {} + + inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) : + MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask, + new uint32_t[obj.mCount], obj.mCount) { + if (mIds != nullptr) { + for (int i = 0; i < mCount; ++i) { + mIds[i] = obj.mIds[i]; + } + } + } + inline virtual ~MsgGnssGetConfig() + { + 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; + } + } + + 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& 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; + retVal = true; + } else { + // Parse the vector and convert SV IDs to mask values + for (GnssSvIdSource source : blacklistedSvIds) { + uint64_t* svMaskPtr = NULL; + GnssSvId initialSvId = 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; + 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 { + *svMaskPtr |= (1 << (source.svId - initialSvId)); + } + } + } + + // Return true if any one source is valid + if (0 != config.gloBlacklistSvMask || + 0 != config.bdsBlacklistSvMask || + 0 != config.galBlacklistSvMask || + 0 != config.qzssBlacklistSvMask) { + retVal = true; + } + } + + return retVal; +} + +void GnssAdapter::convertFromGnssSvIdConfig( + const GnssSvIdConfig& svConfig, GnssConfig& config) +{ + // Convert blacklisted SV mask values to vectors + if (svConfig.bdsBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.bdsBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.galBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.galBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.gloBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.gloBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } + if (svConfig.qzssBlacklistSvMask) { + convertGnssSvIdMaskToList( + svConfig.qzssBlacklistSvMask, config.blacklistedSvIds, + GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS); + config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + } +} + +void GnssAdapter::convertGnssSvIdMaskToList( + uint64_t svIdMask, std::vector& 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) { + 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; + 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); + LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 + ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64, + svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask, + svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask); + mControlCallbacks.gnssConfigCb(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); + + 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; + } + } + + // 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) { + mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(), + [this, sessionId] (LocationError err) { + reportResponse(err, sessionId); + })); +} + uint32_t GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data) { @@ -920,30 +1806,30 @@ GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data) struct MsgDeleteAidingData : public LocMsg { GnssAdapter& mAdapter; - LocApiBase& mApi; uint32_t mSessionId; GnssAidingData mData; inline MsgDeleteAidingData(GnssAdapter& adapter, - LocApiBase& api, uint32_t sessionId, GnssAidingData& data) : LocMsg(), mAdapter(adapter), - mApi(api), mSessionId(sessionId), mData(data) {} inline virtual void proc() const { - LocationError err = LOCATION_ERROR_SUCCESS; - err = mApi.deleteAidingData(mData); - mAdapter.reportResponse(err, mSessionId); - SystemStatus* s = mAdapter.getSystemStatus(); - if ((nullptr != s) && (mData.deleteAll)) { - s->setDefaultGnssEngineStates(); + if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) { + mAdapter.deleteAidingData(mData, mSessionId); + + SystemStatus* s = mAdapter.getSystemStatus(); + if ((nullptr != s) && (mData.deleteAll)) { + s->setDefaultGnssEngineStates(); + } } + + mAdapter.mEngHubProxy->gnssDeleteAidingData(mData); } }; - sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data)); + sendMsg(new MsgDeleteAidingData(*this, sessionId, data)); return sessionId; } @@ -976,28 +1862,66 @@ GnssAdapter::injectLocationCommand(double latitude, double longitude, float accu struct MsgInjectLocation : public LocMsg { LocApiBase& mApi; ContextBase& mContext; + BlockCPIInfo& mBlockCPI; double mLatitude; double mLongitude; float mAccuracy; inline MsgInjectLocation(LocApiBase& api, ContextBase& context, + BlockCPIInfo& blockCPIInfo, double latitude, double longitude, float accuracy) : LocMsg(), mApi(api), mContext(context), + mBlockCPI(blockCPIInfo), mLatitude(latitude), mLongitude(longitude), mAccuracy(accuracy) {} inline virtual void proc() const { - if (!mContext.hasCPIExtendedCapabilities()) { + if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) && + (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) && + (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) { + + LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f", + __func__, mLatitude, mLongitude, mAccuracy); + + } else { mApi.injectPosition(mLatitude, mLongitude, mAccuracy); } } }; - sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy)); + sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo, + latitude, longitude, accuracy)); +} + +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 @@ -1031,56 +1955,41 @@ GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t unce 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::setUlpProxyCommand(UlpProxyBase* ulp) +GnssAdapter::blockCPICommand(double latitude, double longitude, + float accuracy, int blockDurationMsec, + double latLonDiffThreshold) { - LOC_LOGD("%s]: ", __func__); - - struct MsgSetUlpProxy : public LocMsg { - GnssAdapter& mAdapter; - UlpProxyBase* mUlp; - inline MsgSetUlpProxy(GnssAdapter& adapter, - UlpProxyBase* ulp) : - LocMsg(), - mAdapter(adapter), - mUlp(ulp) {} + struct MsgBlockCPI : public LocMsg { + BlockCPIInfo& mDstCPIInfo; + BlockCPIInfo mSrcCPIInfo; + + inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo, + BlockCPIInfo& srcCPIInfo) : + mDstCPIInfo(dstCPIInfo), + mSrcCPIInfo(srcCPIInfo) {} inline virtual void proc() const { - mAdapter.setUlpProxy(mUlp); - if (mUlp) { - mUlp->setCapabilities(ContextBase::getCarrierCapabilities()); - } + // in the same hal thread, save the cpi to be blocked + // the global variable + mDstCPIInfo = mSrcCPIInfo; } }; - sendMsg(new MsgSetUlpProxy(*this, ulp)); -} - -void -GnssAdapter::setUlpProxy(UlpProxyBase* ulp) -{ - if (ulp == mUlpProxy) { - //This takes care of the case when double initalization happens - //and we get the same object back for UlpProxyBase . Do nothing - return; - } - - LOC_LOGV("%s]: %p", __func__, ulp); - if (NULL == ulp) { - LOC_LOGE("%s]: ulp pointer is NULL", __func__); - ulp = new UlpProxyBase(); - } - - if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) { - // need to send this mode and start msg to ULP - ulp->sendFixMode(mUlpProxy->mPosMode); - } - - if (mUlpProxy->mFixSet) { - ulp->sendStartFix(); - } - - delete mUlpProxy; - mUlpProxy = ulp; + // 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 @@ -1100,6 +2009,8 @@ GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& call 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); } }; @@ -1108,38 +2019,32 @@ GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& call } void -GnssAdapter::removeClientCommand(LocationAPI* client) +GnssAdapter::stopClientSessions(LocationAPI* client) { LOC_LOGD("%s]: client %p", __func__, client); - struct MsgRemoveClient : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - inline MsgRemoveClient(GnssAdapter& adapter, - LocationAPI* client) : - LocMsg(), - mAdapter(adapter), - mClient(client) {} - inline virtual void proc() const { - mAdapter.stopClientSessions(mClient); - mAdapter.eraseClient(mClient); + /* Time-based Tracking */ + std::vector vTimeBasedTrackingClient; + for (auto it : mTimeBasedTrackingSessions) { + if (client == it.first.client) { + vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id); } - }; - - sendMsg(new MsgRemoveClient(*this, client)); -} + } + for (auto key : vTimeBasedTrackingClient) { + stopTimeBasedTrackingMultiplex(key.client, key.id); + } -void -GnssAdapter::stopClientSessions(LocationAPI* client) -{ - LOC_LOGD("%s]: client %p", __func__, client); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) { + /* Distance-based Tracking */ + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) { if (client == it->first.client) { - LocationError err = stopTrackingMultiplex(it->first.client, it->first.id); - if (LOCATION_ERROR_SUCCESS == err) { - it = mTrackingSessions.erase(it); - continue; - } + 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 } @@ -1151,12 +2056,9 @@ GnssAdapter::updateClientsEventMask() { LOC_API_ADAPTER_EVENT_MASK_T mask = 0; for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (it->second.trackingCb != nullptr) { + if (it->second.trackingCb != nullptr || it->second.gnssLocationInfoCb != nullptr) { mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT; } - if (it->second.gnssNiCb != nullptr) { - mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; - } if (it->second.gnssSvCb != nullptr) { mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT; } @@ -1166,46 +2068,78 @@ GnssAdapter::updateClientsEventMask() 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 and POLY - ** when QDR is enabled + ** 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) { + if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) || + (true == initEngHubProxy())) { mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; + mask |= LOC_API_ADAPTER_BIT_GNSS_NHZ_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; + mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO; + mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO; - LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%" PRIu64 "", __func__, mask); + LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "", + mask); } - if (mAgpsCbInfo.statusV4Cb != NULL) { + 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; + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); } void GnssAdapter::handleEngineUpEvent() { - struct MsgRestartSessions : public LocMsg { + LOC_LOGD("%s]: ", __func__); + + struct MsgHandleEngineUpEvent : public LocMsg { GnssAdapter& mAdapter; - inline MsgRestartSessions(GnssAdapter& adapter) : + 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.restartSessions(); + mAdapter.gnssSvIdConfigUpdate(); + mAdapter.gnssSvTypeConfigUpdate(); + for (auto msg: mAdapter.mPendingMsgs) { + mAdapter.sendMsg(msg); + } + mAdapter.mPendingMsgs.clear(); } }; - setConfigCommand(); - sendMsg(new MsgRestartSessions(*this)); + readConfigCommand(); + sendMsg(new MsgHandleEngineUpEvent(*this)); } void @@ -1216,131 +2150,87 @@ GnssAdapter::restartSessions() // odcpi session is no longer active after restart mOdcpiRequestActive = false; - if (mTrackingSessions.empty()) { - return; - } - - // get the LocationOptions that has the smallest interval, which should be the active one - LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { - if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet - it->second.minInterval < smallestIntervalOptions.minInterval) { - smallestIntervalOptions = it->second; + 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); + mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr); } - LocPosMode locPosMode = {}; - convertOptions(locPosMode, smallestIntervalOptions); - mLocApi->startFix(locPosMode); + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); ++it) { + mLocApi->startDistanceBasedTracking(it->first.id, it->second, + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + } } void -GnssAdapter::requestCapabilitiesCommand(LocationAPI* client) -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgRequestCapabilities : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - inline MsgRequestCapabilities(GnssAdapter& adapter, - LocationAPI* client) : - LocMsg(), - mAdapter(adapter), - mClient(client) {} - inline virtual void proc() const { - LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient); - if (callbacks.capabilitiesCb == nullptr) { - LOC_LOGE("%s]: capabilitiesCb is NULL", __func__); - return; +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; + } } - - LocationCapabilitiesMask mask = mAdapter.getCapabilities(); - callbacks.capabilitiesCb(mask); } - }; - - sendMsg(new MsgRequestCapabilities(*this, client)); -} - -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 (mLocApi == nullptr) - return mask; - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) { - mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT | - LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT; - } - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { - mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT; - } - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) { - mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT; - } - if (mLocApi->gnssConstellationConfig()) { - mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT; - } - if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { - mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT; - } - return mask; -} -void -GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask) -{ - for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.capabilitiesCb) { - it->second.capabilitiesCb(mask); + if (notifyClientOfSystemInfo) { + callbacks.locationSystemInfoCb(mLocSystemInfo); } } } -LocationCallbacks -GnssAdapter::getClientCallbacks(LocationAPI* client) +bool +GnssAdapter::hasTrackingCallback(LocationAPI* client) { - LocationCallbacks callbacks = {}; auto it = mClientData.find(client); - if (it != mClientData.end()) { - callbacks = it->second; - } - return callbacks; + return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb)); } -void -GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) -{ - mClientData[client] = callbacks; - updateClientsEventMask(); -} - -void -GnssAdapter::eraseClient(LocationAPI* client) +bool +GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId) { - auto it = mClientData.find(client); - if (it != mClientData.end()) { - mClientData.erase(it); - } - updateClientsEventMask(); + LocationSessionKey key(client, sessionId); + return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end()); } bool -GnssAdapter::hasTrackingCallback(LocationAPI* client) +GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId) { - auto it = mClientData.find(client); - return (it != mClientData.end() && it->second.trackingCb); + LocationSessionKey key(client, sessionId); + return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end()); } bool @@ -1354,31 +2244,78 @@ bool GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId) { LocationSessionKey key(client, sessionId); - return (mTrackingSessions.find(key) != mTrackingSessions.end()); + 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(void* powerStateCb) +{ + LOC_LOGD("%s]: ", __func__); + + struct MsgReportLocation : public LocMsg { + GnssAdapter& mAdapter; + powerStateCallback mPowerStateCb; + inline MsgReportLocation(GnssAdapter& adapter, + powerStateCallback powerStateCb) : + LocMsg(), + mAdapter(adapter), + mPowerStateCb(powerStateCb) {} + inline virtual void proc() const { + mAdapter.savePowerStateCallback(mPowerStateCb); + mPowerStateCb(mAdapter.getPowerState()); + } + }; + + sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb)); } void GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId, - const LocationOptions& options) + const TrackingOptions& options) { LocationSessionKey key(client, sessionId); - mTrackingSessions[key] = options; + 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 = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - mTrackingSessions.erase(it); + 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::setUlpPositionMode(const LocPosMode& mode) { - if (!mUlpPositionMode.equals(mode)) { - mUlpPositionMode = mode; + +bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) { + if (!mLocPositionMode.equals(mode)) { + mLocPositionMode = mode; return true; } else { return false; @@ -1391,8 +2328,7 @@ GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t ses 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) { + 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); @@ -1438,23 +2374,24 @@ GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids) } uint32_t -GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) +GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options) { uint32_t sessionId = generateSessionId(); - LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", - __func__, client, sessionId, options.minInterval, options.mode); + 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; - LocationOptions mOptions; + mutable TrackingOptions mOptions; inline MsgStartTracking(GnssAdapter& adapter, LocApiBase& api, LocationAPI* client, uint32_t sessionId, - LocationOptions options) : + TrackingOptions options) : LocMsg(), mAdapter(adapter), mApi(api), @@ -1462,6 +2399,11 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) 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.hasTrackingCallback(mClient) && !mAdapter.hasMeasurementsCallback(mClient)) { @@ -1469,13 +2411,39 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) } else if (0 == mOptions.size) { err = LOCATION_ERROR_INVALID_PARAMETER; } else { - // Api doesn't support multiple clients for time based tracking, so mutiplex - err = mAdapter.startTrackingMultiplex(mOptions); - if (LOCATION_ERROR_SUCCESS == err) { + 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); + } } } - mAdapter.reportResponse(mClient, err, mSessionId); } }; @@ -1484,110 +2452,110 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) } -LocationError -GnssAdapter::startTrackingMultiplex(const LocationOptions& options) +bool +GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& options) { - LocationError err = LOCATION_ERROR_SUCCESS; + bool reportToClientWithNoWait = true; - if (mTrackingSessions.empty()) { - err = startTracking(options); + if (mTimeBasedTrackingSessions.empty()) { + startTimeBasedTracking(client, sessionId, options); + // need to wait for QMI callback + reportToClientWithNoWait = false; } else { - // get the LocationOptions that has the smallest interval, which should be the active one - LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { - if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet - it->second.minInterval < smallestIntervalOptions.minInterval) { - smallestIntervalOptions = it->second; + // 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; } } - // if new session's minInterval is smaller than any in other sessions - if (options.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with new options - err = startTracking(options); + 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; } - } - - return err; -} + // 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 -LocationError -GnssAdapter::startTracking(const LocationOptions& options) -{ - LocationError err = LOCATION_ERROR_SUCCESS; - LocPosMode locPosMode = {}; - convertOptions(locPosMode, options); - if (!mUlpProxy->sendFixMode(locPosMode)) { - // do nothing - } - if (!mUlpProxy->sendStartFix()) { - loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode); - if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { - err = LOCATION_ERROR_SUCCESS; - } else { - err = LOCATION_ERROR_GENERAL_FAILURE; + 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 err; + return reportToClientWithNoWait; } void -GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode) +GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& trackingOptions) { - LOC_LOGD("%s]: min_interval %u mode %u", - __func__, locPosMode.min_interval, locPosMode.mode); - - struct MsgSetPositionMode : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocPosMode mLocPosMode; - inline MsgSetPositionMode(GnssAdapter& adapter, - LocApiBase& api, - LocPosMode& locPosMode) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mLocPosMode(locPosMode) {} - inline virtual void proc() const { - // saves the mode in adapter to be used when startTrackingCommand is called from ULP - if (mAdapter.setUlpPositionMode(mLocPosMode)) { - mApi.setPositionMode(mLocPosMode); + 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); + + // inform engine hub that GNSS session is about to start + mEngHubProxy->gnssSetFixMode(locPosMode); + mEngHubProxy->gnssStartFix(); + + mLocApi->startTimeBasedTracking(trackingOptions, new LocApiResponse(*getContext(), + [this, client, sessionId] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + eraseTrackingSession(client, sessionId); } - } - }; - sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode)); + reportResponse(client, err, sessionId); + } + )); } void -GnssAdapter::startTrackingCommand() +GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId, + const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions) { - LOC_LOGD("%s]: ", __func__); + LocPosMode locPosMode = {}; + convertOptions(locPosMode, updatedOptions); - struct MsgStartTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgStartTracking(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - // we get this call from ULP, so just call LocApi without multiplexing because - // ulp would be doing the multiplexing for us if it is present - if (!mAdapter.isInSession()) { - LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode(); - mApi.startFix(ulpPositionMode); + // inform engine hub that GNSS session is about to start + mEngHubProxy->gnssSetFixMode(locPosMode); + mEngHubProxy->gnssStartFix(); + + mLocApi->startTimeBasedTracking(updatedOptions, new LocApiResponse(*getContext(), + [this, client, sessionId, oldOptions] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + // restore the old LocationOptions + saveTrackingSession(client, sessionId, oldOptions); } - } - }; - sendMsg(new MsgStartTracking(*this, *mLocApi)); + reportResponse(client, err, sessionId); + } + )); } void GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, - LocationOptions& options) + TrackingOptions& options) { LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", __func__, client, id, options.minInterval, options.mode); @@ -1597,12 +2565,12 @@ GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, LocApiBase& mApi; LocationAPI* mClient; uint32_t mSessionId; - LocationOptions mOptions; + mutable TrackingOptions mOptions; inline MsgUpdateTracking(GnssAdapter& adapter, LocApiBase& api, LocationAPI* client, uint32_t sessionId, - LocationOptions options) : + TrackingOptions options) : LocMsg(), mAdapter(adapter), mApi(api), @@ -1610,65 +2578,163 @@ GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, mSessionId(sessionId), mOptions(options) {} inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - LocationError err = LOCATION_ERROR_SUCCESS; - if (0 == mOptions.size) { - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { + // 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 - err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions); - if (LOCATION_ERROR_SUCCESS == err) { + 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); + })); + } + })); } - mAdapter.reportResponse(mClient, err, mSessionId); } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since updateTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response } }; sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options)); } -LocationError +bool GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id, - const LocationOptions& options) + const TrackingOptions& trackingOptions) { - LocationError err = LOCATION_ERROR_SUCCESS; - - if (1 == mTrackingSessions.size()) { - err = startTracking(options); - } else { - LocationSessionKey key(client, id); - - // get the session we are updating - auto it = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - // find the smallest interval, other than the session we are updating - LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { - // if session is not the one we are updating and either smallest interval is not set - // or there is a new smallest interval, then set the new smallest interval - if (it2->first != key && (0 == smallestIntervalOptions.size || - it2->second.minInterval < smallestIntervalOptions.minInterval)) { - smallestIntervalOptions = it2->second; - } + 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 we are updating has smaller interval then next smallest - if (options.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with the newly updated interval - err = startTracking(options); - // else if the session we are updating used to be the smallest - } else if (it->second.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with the next smallest - err = startTracking(smallestIntervalOptions); + // 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 err; + return reportToClientWithNoWait; } void @@ -1691,18 +2757,32 @@ GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) mClient(client), mSessionId(sessionId) {} inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - LocationError err = LOCATION_ERROR_SUCCESS; - // Api doesn't support multiple clients for time based tracking, so mutiplex - err = mAdapter.stopTrackingMultiplex(mClient, mSessionId); - if (LOCATION_ERROR_SUCCESS == err) { + 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); + })); } - mAdapter.reportResponse(mClient, err, mSessionId); + } else { + mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId); } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since stopTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response } }; @@ -1710,115 +2790,67 @@ GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) sendMsg(new MsgStopTracking(*this, *mLocApi, client, id)); } -LocationError -GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) +bool +GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id) { - LocationError err = LOCATION_ERROR_SUCCESS; + bool reportToClientWithNoWait = true; - if (1 == mTrackingSessions.size()) { - err = stopTracking(); + 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 = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - // find the next smallest interval, other than the session we are stopping - LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { - // if session is not the one we are stopping and either smallest interval is not set - // or there is a new smallest interval, then set the new smallest interval - if (it2->first != key && (0 == smallestIntervalOptions.size || - it2->second.minInterval < smallestIntervalOptions.minInterval)) { - smallestIntervalOptions = it2->second; + 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 - if (it->second.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with next smallest interval - err = startTracking(smallestIntervalOptions); + // 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 err; -} - -LocationError -GnssAdapter::stopTracking() -{ - LocationError err = LOCATION_ERROR_SUCCESS; - if (!mUlpProxy->sendStopFix()) { - loc_api_adapter_err apiErr = mLocApi->stopFix(); - if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { - err = LOCATION_ERROR_SUCCESS; - } else { - err = LOCATION_ERROR_GENERAL_FAILURE; - } - } - - return err; -} - -void -GnssAdapter::stopTrackingCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgStopTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgStopTracking(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - // clear the position mode - LocPosMode mLocPosMode = {}; - mLocPosMode.mode = LOC_POSITION_MODE_INVALID; - mAdapter.setUlpPositionMode(mLocPosMode); - // don't need to multiplex because ULP will do that for us if it is present - mApi.stopFix(); - } - }; - - sendMsg(new MsgStopTracking(*this, *mLocApi)); + return reportToClientWithNoWait; } void -GnssAdapter::getZppCommand() +GnssAdapter::stopTracking(LocationAPI* client, uint32_t id) { - LOC_LOGD("%s]: ", __func__); - - struct MsgGetZpp : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgGetZpp(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - UlpLocation location = {}; - LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT; - GpsLocationExtended locationExtended = {}; - locationExtended.size = sizeof(locationExtended); - - mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended, - techMask); - //Mark the location source as from ZPP - location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; - location.position_source = ULP_LOCATION_IS_FROM_ZPP; - - mAdapter.getUlpProxy()->reportPosition(location, - locationExtended, - LOC_SESS_SUCCESS, - techMask); - } - }; + // inform engine hub that GNSS session has stopped + mEngHubProxy->gnssStopFix(); - sendMsg(new MsgGetZpp(*this, *mLocApi)); + mLocApi->stopFix(new LocApiResponse(*getContext(), + [this, client, id] (LocationError err) { + reportResponse(client, err, id); + })); } bool @@ -1901,28 +2933,27 @@ 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(LocApiBase& api, + inline MsgGnssNiResponse(GnssAdapter& adapter, + LocApiBase& api, const GnssNiResponse response, const void* rawRequest) : LocMsg(), + mAdapter(adapter), mApi(api), mResponse(response), mPayload(rawRequest) {} inline virtual ~MsgGnssNiResponse() { - // this is a bit weird since mPayload is not - // allocated by this class. But there is no better way. - // mPayload actually won't be NULL here. - free((void*)mPayload); } inline virtual void proc() const { mApi.informNiResponse(mResponse, mPayload); } }; - sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest)); + sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest)); } @@ -1951,17 +2982,24 @@ GnssAdapter::enableCommand(LocationTechnologyType techType) mTechType(techType) {} inline virtual void proc() const { LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); + uint32_t afwControlId = mAdapter.getAfwControlId(); if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) { err = LOCATION_ERROR_INVALID_PARAMETER; - } else if (powerVoteId > 0) { + } else if (afwControlId > 0) { err = LOCATION_ERROR_ALREADY_STARTED; } else { mContext.modemPowerVote(true); - mAdapter.setPowerVoteId(mSessionId); - mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE); - mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE)); + 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); } @@ -1997,15 +3035,22 @@ GnssAdapter::disableCommand(uint32_t id) mSessionId(sessionId) {} inline virtual void proc() const { LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); - if (powerVoteId != mSessionId) { + uint32_t afwControlId = mAdapter.getAfwControlId(); + if (afwControlId != mSessionId) { err = LOCATION_ERROR_ID_UNKNOWN; } else { mContext.modemPowerVote(false); - mAdapter.setPowerVoteId(0); - mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); - mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); + 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); } @@ -2022,35 +3067,56 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask techMask, - bool fromUlp) + GnssDataNotification* pDataNotify, + int msInWeek) { - LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status); + // this position is from QMI LOC API, then send report to engine hub + // if sending is successful, we return as we will wait for final report from engine hub + // if the position is called from engine hub, then send it out directly - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp) { - if (mUlpProxy->reportPosition(ulpLocation, locationExtended, - status, techMask)) { - return; - } + if (true == initEngHubProxy()){ + mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status); + return; + } + + if (true == ulpLocation.unpropagatedPosition) { + return; } + // Fix is from QMI, and it is not an + // unpropagated position and engine hub is not loaded, queue the msg + // when message is queued, the position can be dispatched to requesting client struct MsgReportPosition : public LocMsg { GnssAdapter& mAdapter; const UlpLocation mUlpLocation; const GpsLocationExtended mLocationExtended; loc_sess_status mStatus; LocPosTechMask mTechMask; + GnssDataNotification mDataNotify; + int mMsInWeek; + bool mbIsDataValid; inline MsgReportPosition(GnssAdapter& adapter, const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, loc_sess_status status, - LocPosTechMask techMask) : + LocPosTechMask techMask, + GnssDataNotification* pDataNotify, + int msInWeek) : LocMsg(), mAdapter(adapter), mUlpLocation(ulpLocation), mLocationExtended(locationExtended), mStatus(status), - mTechMask(techMask) {} + mTechMask(techMask), + mMsInWeek(msInWeek) { + memset(&mDataNotify, 0, sizeof(mDataNotify)); + if (pDataNotify != nullptr) { + mDataNotify = *pDataNotify; + mbIsDataValid = true; + } else { + mbIsDataValid = false; + } + } inline virtual void proc() const { // extract bug report info - this returns true if consumed by systemstatus SystemStatus* s = mAdapter.getSystemStatus(); @@ -2059,98 +3125,215 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, s->eventPosition(mUlpLocation, mLocationExtended); } mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask); + if (true == mbIsDataValid) { + if (-1 != mMsInWeek) { + mAdapter.getDataInformation((GnssDataNotification&)mDataNotify, + mMsInWeek); + } + mAdapter.reportData((GnssDataNotification&)mDataNotify); + } + } + }; + + sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, + status, techMask, + pDataNotify, 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 MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask)); + sendMsg(new MsgReportEnginePositions(*this, count, locationArr)); } bool -GnssAdapter::needReport(const UlpLocation& ulpLocation, - enum loc_sess_status status, - LocPosTechMask techMask) { +GnssAdapter::needReportForGnssClient(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 accepte 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)); - } + // 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 ((status == LOC_SESS_INTERMEDIATE) && + !(techMask & LOC_POS_TECH_MASK_SENSORS) && + (!getAllowFlpNetworkFixes())) { + 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); +} + void GnssAdapter::reportPosition(const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask techMask) { - bool reported = needReport(ulpLocation, status, techMask); - if (reported) { - if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) { - mGnssSvIdUsedInPosAvail = true; - mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids; - } + bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask); + bool reportToFlpClient = needReportForFlpClient(status, techMask); + + if (reportToGnssClient || reportToFlpClient) { + GnssLocationInfoNotification locationInfo = {}; + convertLocationInfo(locationInfo, locationExtended); + convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask); + for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.trackingCb) { - Location location = {}; - convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask); - it->second.trackingCb(location); + 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 (nullptr != it->second.gnssLocationInfoCb) { - GnssLocationInfoNotification locationInfo = {}; - convertLocationInfo(locationInfo, locationExtended); - it->second.gnssLocationInfoCb(locationInfo); + + // if engine hub is running and the fix is from sensor, e.g.: DRE, + // inject DRE fix to modem + if ((1 == ContextBase::mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED) && + (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) { + mLocApi->injectPosition(locationInfo, false); } } } - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { + if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && + !mTimeBasedTrackingSessions.empty()) { /*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 = (reported && status != LOC_SESS_FAILURE && !blank_fix); + 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); std::vector nmeaArraystr; - loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr); - for (auto sentence : nmeaArraystr) { - reportNmea(sentence.c_str(), sentence.length()); + loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, + generate_nmea, custom_nmea_gga, nmeaArraystr); + stringstream ss; + for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { + ss << *itor; + } + string s = ss.str(); + reportNmea(s.c_str(), s.length()); + } +} + +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); + convertLocation(locationInfo[i].location, + engLocation->location, + engLocation->locationExtended, + engLocation->location.tech_mask); } } - // Free the allocated memory for rawData - UlpLocation* gp = (UlpLocation*)&(ulpLocation); - if (gp != NULL && gp->rawData != NULL) - { - delete (char*)gp->rawData; - gp->rawData = NULL; - gp->rawDataSize = 0; + 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 fromUlp) + bool fromEngineHub) { - LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp); - - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp) { - if (mUlpProxy->reportSv(svNotify)) { + if (!fromEngineHub) { + mEngHubProxy->gnssReportSv(svNotify); + if (true == initEngHubProxy()){ return; } } @@ -2180,36 +3363,121 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) 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) { - svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask; + 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) { - svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask; + 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; + } } break; case GNSS_SV_TYPE_BEIDOU: if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask; + 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; + } } break; case GNSS_SV_TYPE_GALILEO: if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask; + 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; + } } break; case GNSS_SV_TYPE_QZSS: if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask; + 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; + } } // QZSS SV id's need to reported as it is to framework, since // framework expects it as it is. See GnssStatus.java. // SV id passed to here by LocApi is 1-based. svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1); break; + case GNSS_SV_TYPE_NAVIC: + if (mGnssSvIdUsedInPosAvail) { + svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask; + } + break; default: svUsedIdMask = 0; break; @@ -2217,7 +3485,7 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) // If SV ID was used in previous position fix, then set USED_IN_FIX // flag, else clear the USED_IN_FIX flag. - if (svUsedIdMask & (1 << (gnssSvId - 1))) { + if ((gnssSvId < 64) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) { svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT; } } @@ -2228,25 +3496,27 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) } } - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { + if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && + !mTimeBasedTrackingSessions.empty()) { std::vector nmeaArraystr; loc_nmea_generate_sv(svNotify, nmeaArraystr); - for (auto sentence : nmeaArraystr) { - reportNmea(sentence.c_str(), sentence.length()); + 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; } void -GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp) +GnssAdapter::reportNmeaEvent(const char* nmea, size_t length) { - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp && !loc_nmea_is_debug(nmea, length)) { - if (mUlpProxy->reportNmea(nmea, length)) { - return; - } + if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && + !loc_nmea_is_debug(nmea, length)) { + return; } struct MsgReportNmea : public LocMsg { @@ -2307,34 +3577,170 @@ GnssAdapter::reportNmea(const char* nmea, size_t length) } } -bool -GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data) -{ - 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); +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 (-1 != mMsInWeek) { + 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 ¬ify, 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 (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) { - struct MsgReportNiNotify : public LocMsg { + // send system info to engine hub + mEngHubProxy->gnssReportSystemInfo(locationSystemInfo); + + struct MsgLocationSystemInfo : public LocMsg { GnssAdapter& mAdapter; - const GnssNiNotification mNotify; - const void* mData; - inline MsgReportNiNotify(GnssAdapter& adapter, - const GnssNiNotification& notify, - const void* data) : + LocationSystemInfo mSystemInfo; + inline MsgLocationSystemInfo(GnssAdapter& adapter, + const LocationSystemInfo& systemInfo) : LocMsg(), mAdapter(adapter), - mNotify(notify), - mData(data) {} + mSystemInfo(systemInfo) {} inline virtual void proc() const { - mAdapter.requestNiNotify(mNotify, mData); + mAdapter.reportLocationSystemInfo(mSystemInfo); } }; - sendMsg(new MsgReportNiNotify(*this, notify, data)); + sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo)); +} - return true; +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) @@ -2399,7 +3805,8 @@ static void* niThreadProc(void *args) } bool -GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) +GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data, + const bool bInformNiAccept) { NiSession* pSession = NULL; gnssNiCallback gnssNiCb = nullptr; @@ -2411,6 +3818,20 @@ GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) } } 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; } @@ -2471,30 +3892,34 @@ GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) } void -GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, +GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements, int msInWeek) { LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek); - struct MsgReportGnssMeasurementData : public LocMsg { - GnssAdapter& mAdapter; - GnssMeasurementsNotification mMeasurementsNotify; - inline MsgReportGnssMeasurementData(GnssAdapter& adapter, - const GnssMeasurementsNotification& measurements, - int msInWeek) : - LocMsg(), - mAdapter(adapter), - mMeasurementsNotify(measurements) { - if (-1 != msInWeek) { - mAdapter.getAgcInformation(mMeasurementsNotify, 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); - } - }; + inline virtual void proc() const { + mAdapter.reportGnssMeasurementData(mMeasurementsNotify); + } + }; - sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek)); + sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek)); + } + mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet); } void @@ -2508,43 +3933,40 @@ GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measu } void -GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet) +GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) { LOC_LOGD("%s]: ", __func__); - - // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. - mUlpProxy->reportSvMeasurement(svMeasurementSet); + mEngHubProxy->gnssReportSvPolynomial(svPolynomial); } void -GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) +GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris) { - LOC_LOGD("%s]: ", __func__); - - // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. - mUlpProxy->reportSvPolynomial(svPolynomial); + LOC_LOGD("%s]:", __func__); + mEngHubProxy->gnssReportSvEphemeris(svEphemeris); } + bool -GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request) +GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request) { - struct MsgReportOdcpiRequest : public LocMsg { + struct MsgRequestOdcpi : public LocMsg { GnssAdapter& mAdapter; OdcpiRequestInfo mOdcpiRequest; - inline MsgReportOdcpiRequest(GnssAdapter& adapter, OdcpiRequestInfo& request) : + inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) : LocMsg(), mAdapter(adapter), mOdcpiRequest(request) {} inline virtual void proc() const { - mAdapter.reportOdcpiRequest(mOdcpiRequest); + mAdapter.requestOdcpi(mOdcpiRequest); } }; - sendMsg(new MsgReportOdcpiRequest(*this, request)); + sendMsg(new MsgRequestOdcpi(*this, request)); return true; } -void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request) +void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request) { if (nullptr != mOdcpiRequestCb) { LOC_LOGd("request: type %d, tbf %d, isEmergency %d" @@ -2589,6 +4011,28 @@ void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request) } } +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; +} + void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback) { struct MsgInitOdcpi : public LocMsg { @@ -2640,10 +4084,7 @@ void GnssAdapter::injectOdcpi(const Location& location) mOdcpiRequestActive, mOdcpiTimer.isActive(), location.latitude, location.longitude); - loc_api_adapter_err err = mLocApi->injectPosition(location); - if (LOC_API_ADAPTER_ERR_SUCCESS != err) { - LOC_LOGe("Inject Position API error %d", err); - } + mLocApi->injectPosition(location, true); } // Called in the context of LocTimer thread @@ -2683,6 +4124,35 @@ void GnssAdapter::odcpiTimerExpire() } } +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__); @@ -2696,6 +4166,7 @@ void GnssAdapter::initDefaultAgps() { dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo"); if (getAgpsCbInfo == nullptr) { LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__); + dlclose(handle); return; } @@ -2703,6 +4174,7 @@ void GnssAdapter::initDefaultAgps() { if (cbInfo.statusV4Cb == nullptr) { LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__); + dlclose(handle); return; } @@ -2729,27 +4201,17 @@ void GnssAdapter::initDefaultAgpsCommand() { /* INIT LOC AGPS MANAGER */ void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) { - LOC_LOGD("%s]: mAgpsCbInfo.cbPriority - %d; cbInfo.cbPriority - %d", - __func__, mAgpsCbInfo.cbPriority, cbInfo.cbPriority) + 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; } - if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) { - return; - } else { - mAgpsCbInfo = cbInfo; - - mAgpsManager.registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb); - - mAgpsManager.createAgpsStateMachines(); - - /* Register for AGPS event mask */ - updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST, - LOC_REGISTRATION_MASK_ENABLED); - } + 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){ @@ -2776,33 +4238,68 @@ void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){ sendMsg(new AgpsMsgInit(cbInfo, *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 */ -bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){ +void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) { + LOC_LOGi("GnssAdapter::initNfwCommand"); + + /* Message to initialize NFW */ + struct MsgInitNfw : public LocMsg { + const NfwCbInfo mCbInfo; + GnssAdapter& mAdapter; - LOC_LOGI("GnssAdapter::requestATL"); + inline MsgInitNfw(const NfwCbInfo& cbInfo, + GnssAdapter& adapter) : + LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) { + LOC_LOGv("MsgInitNfw"); + } - sendMsg( new AgpsMsgRequestATL( - &mAgpsManager, connHandle, (AGpsExtType)agpsType)); + inline virtual void proc() const { + LOC_LOGv("MsgInitNfw::proc()"); + mAdapter.initNfw(mCbInfo); + } + }; - return true; + /* 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::requestSuplES +/* 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::requestSuplES(int connHandle){ +bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType, + LocApnTypeMask apnTypeMask){ - LOC_LOGI("GnssAdapter::requestSuplES"); + LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X", + connHandle, agpsType, apnTypeMask); sendMsg( new AgpsMsgRequestATL( - &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES)); + &mAgpsManager, connHandle, (AGpsExtType)agpsType, + apnTypeMask)); return true; } @@ -2839,64 +4336,6 @@ bool GnssAdapter::releaseATL(int connHandle){ return true; } -/* GnssAdapter::reportDataCallOpened - * DS Client data call opened successfully. - * Send message to AGPS Manager to handle. */ -bool GnssAdapter::reportDataCallOpened(){ - - LOC_LOGI("GnssAdapter::reportDataCallOpened"); - - struct AgpsMsgSuplEsOpened: public LocMsg { - - AgpsManager* mAgpsManager; - - inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) : - LocMsg(), mAgpsManager(agpsManager) { - - LOC_LOGV("AgpsMsgSuplEsOpened"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgSuplEsOpened::proc()"); - mAgpsManager->reportDataCallOpened(); - } - }; - - sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager)); - - return true; -} - -/* GnssAdapter::reportDataCallClosed - * DS Client data call closed. - * Send message to AGPS Manager to handle. */ -bool GnssAdapter::reportDataCallClosed(){ - - LOC_LOGI("GnssAdapter::reportDataCallClosed"); - - struct AgpsMsgSuplEsClosed: public LocMsg { - - AgpsManager* mAgpsManager; - - inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) : - LocMsg(), mAgpsManager(agpsManager) { - - LOC_LOGV("AgpsMsgSuplEsClosed"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgSuplEsClosed::proc()"); - mAgpsManager->reportDataCallClosed(); - } - }; - - sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager)); - - return true; -} - void GnssAdapter::dataConnOpenCommand( AGpsExtType agpsType, const char* apnName, int apnLen, AGpsBearerType bearerType){ @@ -2919,6 +4358,8 @@ void GnssAdapter::dataConnOpenCommand( 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); @@ -2935,9 +4376,15 @@ void GnssAdapter::dataConnOpenCommand( mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType); } }; - - sendMsg( new AgpsMsgAtlOpenSuccess( - &mAgpsManager, agpsType, apnName, apnLen, bearerType)); + // 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) != 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){ @@ -3071,6 +4518,19 @@ void GnssAdapter::convertSatelliteInfo(std::vector& out, 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; } @@ -3200,9 +4660,18 @@ bool GnssAdapter::getDebugReport(GnssDebugReport& r) (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL + (int64_t)(reports.mTimeAndClock.back().mGpsTowMs); - r.mTime.timeUncertaintyNs = - ((float)(reports.mTimeAndClock.back().mTimeUnc) + - (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f; + 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", @@ -3219,6 +4688,7 @@ bool GnssAdapter::getDebugReport(GnssDebugReport& r) 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; @@ -3278,6 +4748,94 @@ GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int m } } +/* 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) { @@ -3311,3 +4869,179 @@ static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userD 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"); + } +} + +/* ==== 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; + break; + } + } + + // no plugin daemon is enabled for this platform, no need to load eng hub .so + if (pluginDaemonEnabled == false) { + 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); + }; + + getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy"); + if(getter != nullptr) { + EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(), + reportPositionEventCb, + reportSvEventCb, reqAidingDataCb); + 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; +} diff --git a/gps/gnss/GnssAdapter.h b/gps/gnss/GnssAdapter.h index 0609e6d..3ccdd96 100644 --- a/gps/gnss/GnssAdapter.h +++ b/gps/gnss/GnssAdapter.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -30,12 +30,14 @@ #define GNSS_ADAPTER_H #include -#include -#include +#include +#include +#include #include #include #include #include +#include #define MAX_URL_LEN 256 #define NMEA_SENTENCE_MAX_LENGTH 200 @@ -47,6 +49,9 @@ class GnssAdapter; +typedef std::map LocationSessionMap; +typedef std::map TrackingOptionsMap; + class OdcpiTimer : public LocTimer { public: OdcpiTimer(GnssAdapter* adapter) : @@ -104,31 +109,53 @@ typedef struct { 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; + using namespace loc_core; namespace loc_core { class SystemStatus; } -class GnssAdapter : public LocAdapterBase { +typedef std::function GnssEnergyConsumedCallback; - /* ==== ULP ============================================================================ */ - UlpProxyBase* mUlpProxy; +typedef void (*powerStateCallback)(bool on); - /* ==== CLIENT ========================================================================= */ - typedef std::map ClientDataMap; - ClientDataMap mClientData; +class GnssAdapter : public LocAdapterBase { + + /* ==== Engine Hub ===================================================================== */ + EngineHubProxyBase* mEngHubProxy; /* ==== TRACKING ======================================================================= */ - LocationSessionMap mTrackingSessions; - LocPosMode mUlpPositionMode; + TrackingOptionsMap mTimeBasedTrackingSessions; + LocationSessionMap mDistanceBasedTrackingSessions; + LocPosMode mLocPositionMode; GnssSvUsedInPosition mGnssSvIdUsedInPosition; bool mGnssSvIdUsedInPosAvail; + GnssSvMbUsedInPosition mGnssMbSvIdUsedInPosition; + bool mGnssMbSvIdUsedInPosAvail; /* ==== CONTROL ======================================================================== */ LocationControlCallbacks mControlCallbacks; - uint32_t mPowerVoteId; + uint32_t mAfwControlId; uint32_t mNmeaMask; + GnssSvIdConfig mGnssSvIdConfig; + GnssSvTypeConfig mGnssSvTypeConfig; + GnssSvTypeConfigCallback mGnssSvTypeConfigCb; + bool mSupportNfwControl; /* ==== NI ============================================================================= */ NiData mNiData; @@ -136,9 +163,16 @@ class GnssAdapter : public LocAdapterBase { /* ==== AGPS =========================================================================== */ // This must be initialized via initAgps() AgpsManager mAgpsManager; - AgpsCbInfo mAgpsCbInfo; void initAgps(const AgpsCbInfo& cbInfo); + /* ==== NFW =========================================================================== */ + NfwStatusCb mNfwCb; + IsInEmergencySession mIsE911Session; + inline void initNfw(const NfwCbInfo& cbInfo) { + mNfwCb = (NfwStatusCb)cbInfo.visibilityControlCb; + mIsE911Session = (IsInEmergencySession)cbInfo.isInEmergencySession; + } + /* ==== ODCPI ========================================================================== */ OdcpiRequestCallback mOdcpiRequestCb; bool mOdcpiRequestActive; @@ -149,20 +183,45 @@ class GnssAdapter : public LocAdapterBase { /* === SystemStatus ===================================================================== */ SystemStatus* mSystemStatus; std::string mServerUrl; + std::string mMoServerUrl; XtraSystemStatusObserver mXtraObserver; + LocationSystemInfo mLocSystemInfo; + std::vector mBlacklistedSvIds; + + /* === Misc ===================================================================== */ + BlockCPIInfo mBlockCPIInfo; + bool mPowerOn; + uint32_t mAllowFlpNetworkFixes; + + /* === Misc callback from QMI LOC API ============================================== */ + GnssEnergyConsumedCallback mGnssEnergyConsumedCb; + powerStateCallback mPowerStateCb; /*==== CONVERSION ===================================================================*/ - static void convertOptions(LocPosMode& out, const LocationOptions& options); - static void convertLocation(Location& out, const LocGpsLocation& locGpsLocation, + static void convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions); + static void convertLocation(Location& out, const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, const LocPosTechMask techMask); static void convertLocationInfo(GnssLocationInfoNotification& out, const GpsLocationExtended& locationExtended); + static uint16_t getNumSvUsed(uint64_t svUsedIdsMask, + int totalSvCntInThisConstellation); + + /* ======== UTILITIES ================================================================== */ + inline void initOdcpi(const OdcpiRequestCallback& callback); + inline void injectOdcpi(const Location& location); + static bool isFlpClient(LocationCallbacks& locationCallbacks); + +protected: + + /* ==== CLIENT ========================================================================= */ + virtual void updateClientsEventMask(); + virtual void stopClientSessions(LocationAPI* client); public: GnssAdapter(); - virtual inline ~GnssAdapter() { delete mUlpProxy; } + virtual inline ~GnssAdapter() { } /* ==== SSR ============================================================================ */ /* ======== EVENTS ====(Called from QMI Thread)========================================= */ @@ -170,55 +229,42 @@ public: /* ======== UTILITIES ================================================================== */ void restartSessions(); - /* ==== ULP ============================================================================ */ - /* ======== COMMANDS ====(Called from ULP Thread)==================================== */ - virtual void setUlpProxyCommand(UlpProxyBase* ulp); - /* ======== UTILITIES ================================================================== */ - void setUlpProxy(UlpProxyBase* ulp); - inline UlpProxyBase* getUlpProxy() { return mUlpProxy; } - /* ==== CLIENT ========================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ - void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); - void removeClientCommand(LocationAPI* client); - void requestCapabilitiesCommand(LocationAPI* client); - /* ======== UTILITIES ================================================================== */ - void saveClient(LocationAPI* client, const LocationCallbacks& callbacks); - void eraseClient(LocationAPI* client); - void updateClientsEventMask(); - void stopClientSessions(LocationAPI* client); - LocationCallbacks getClientCallbacks(LocationAPI* client); - LocationCapabilitiesMask getCapabilities(); - void broadcastCapabilities(LocationCapabilitiesMask); - LocationError setSuplHostServer(const char* server, int port); + virtual void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); /* ==== TRACKING ======================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ - uint32_t startTrackingCommand(LocationAPI* client, LocationOptions& options); - void updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, LocationOptions& options); + uint32_t startTrackingCommand( + LocationAPI* client, TrackingOptions& trackingOptions); + void updateTrackingOptionsCommand( + LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions); void stopTrackingCommand(LocationAPI* client, uint32_t id); - /* ======================(Called from ULP Thread)======================================= */ - virtual void setPositionModeCommand(LocPosMode& locPosMode); - virtual void startTrackingCommand(); - virtual void stopTrackingCommand(); - virtual void getZppCommand(); /* ======== RESPONSES ================================================================== */ void reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId); /* ======== UTILITIES ================================================================== */ bool hasTrackingCallback(LocationAPI* client); + bool isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId); + bool isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId); bool hasMeasurementsCallback(LocationAPI* client); bool isTrackingSession(LocationAPI* client, uint32_t sessionId); void saveTrackingSession(LocationAPI* client, uint32_t sessionId, - const LocationOptions& options); + const TrackingOptions& trackingOptions); void eraseTrackingSession(LocationAPI* client, uint32_t sessionId); - bool setUlpPositionMode(const LocPosMode& mode); - LocPosMode& getUlpPositionMode() { return mUlpPositionMode; } - LocationError startTrackingMultiplex(const LocationOptions& options); - LocationError startTracking(const LocationOptions& options); - LocationError stopTrackingMultiplex(LocationAPI* client, uint32_t id); - LocationError stopTracking(); - LocationError updateTrackingMultiplex(LocationAPI* client, uint32_t id, - const LocationOptions& options); + + 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); /* ==== NI ============================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -229,33 +275,61 @@ public: bool hasNiNotifyCallback(LocationAPI* client); NiData& getNiData() { return mNiData; } - /* ==== CONTROL ======================================================================== */ + /* ==== CONTROL CLIENT ================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ uint32_t enableCommand(LocationTechnologyType techType); void disableCommand(uint32_t id); void setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks); void readConfigCommand(); - void setConfigCommand(); + void requestUlpCommand(); + void initEngHubProxyCommand(); uint32_t* gnssUpdateConfigCommand(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 gnssUpdateConfig(const std::string& oldMoServerUrl, + const GnssConfig& gnssConfigRequested, + const 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& blacklistedSvIds); + LocationError gnssSvIdConfigUpdateSync(); + void gnssSvIdConfigUpdate(const std::vector& 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(); + + /* ========= 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); /* ========= ODCPI ===================================================================== */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ void initOdcpiCommand(const OdcpiRequestCallback& callback); void injectOdcpiCommand(const Location& location); - /* ======== UTILITIES ================================================================== */ - void initOdcpi(const OdcpiRequestCallback& callback); - void injectOdcpi(const Location& location); - void odcpiTimerExpireEvent(); - /* ======== RESPONSES ================================================================== */ void reportResponse(LocationError err, uint32_t sessionId); void reportResponse(size_t count, LocationError* errs, uint32_t* ids); @@ -263,79 +337,133 @@ public: LocationControlCallbacks& getControlCallbacks() { return mControlCallbacks; } void setControlCallbacks(const LocationControlCallbacks& controlCallbacks) { mControlCallbacks = controlCallbacks; } - void setPowerVoteId(uint32_t id) { mPowerVoteId = id; } - uint32_t getPowerVoteId() { return mPowerVoteId; } - bool resolveInAddress(const char* hostAddress, struct in_addr* inAddress); - virtual bool isInSession() { return !mTrackingSessions.empty(); } + void setAfwControlId(uint32_t id) { mAfwControlId = id; } + uint32_t getAfwControlId() { return mAfwControlId; } + virtual bool isInSession() { return !mTimeBasedTrackingSessions.empty(); } void initDefaultAgps(); + bool initEngHubProxy(); + void odcpiTimerExpireEvent(); /* ==== REPORTS ======================================================================== */ - /* ======== EVENTS ====(Called from QMI/ULP Thread)===================================== */ + /* ======== EVENTS ====(Called from QMI/EngineHub Thread)===================================== */ virtual void reportPositionEvent(const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, enum loc_sess_status status, LocPosTechMask techMask, - bool fromUlp=false); - virtual void reportSvEvent(const GnssSvNotification& svNotify, bool fromUlp=false); - virtual void reportNmeaEvent(const char* nmea, size_t length, bool fromUlp=false); - virtual bool requestNiNotifyEvent(const GnssNiNotification& notify, const void* data); - virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, + 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 reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet); virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial); + virtual void reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris); + virtual void reportGnssSvIdConfigEvent(const GnssSvIdConfig& config); + virtual void reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config); + virtual bool reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot); + virtual void reportLocationSystemInfoEvent(const LocationSystemInfo& locationSystemInfo); - virtual bool requestATL(int connHandle, LocAGpsType agps_type); + virtual bool requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask); virtual bool releaseATL(int connHandle); - virtual bool requestSuplES(int connHandle); - virtual bool reportDataCallOpened(); - virtual bool reportDataCallClosed(); - virtual bool reportOdcpiRequestEvent(OdcpiRequestInfo& request); + 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); /* ======== UTILITIES ================================================================= */ - bool needReport(const UlpLocation& ulpLocation, + bool needReportForGnssClient(const UlpLocation& ulpLocation, enum loc_sess_status status, LocPosTechMask techMask); + bool needReportForFlpClient(enum loc_sess_status status, LocPosTechMask techMask); 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); - bool requestNiNotify(const GnssNiNotification& notify, const void* data); + void reportData(GnssDataNotification& dataNotify); + bool requestNiNotify(const GnssNiNotification& notify, const void* data, + const bool bInformNiAccept); void reportGnssMeasurementData(const GnssMeasurementsNotification& measurements); - void reportOdcpiRequest(const OdcpiRequestInfo& request); + void reportGnssSvIdConfig(const GnssSvIdConfig& config); + void reportGnssSvTypeConfig(const GnssSvTypeConfig& config); + 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; + } /*======== 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; } - void setServerUrl(const char* server) { mServerUrl.assign(server); } + std::string& getMoServerUrl(void) { return mMoServerUrl; } /*==== CONVERSION ===================================================================*/ - static uint32_t convertGpsLock(const GnssConfigGpsLock gpsLock); - static GnssConfigGpsLock convertGpsLock(const uint32_t gpsLock); static uint32_t convertSuplVersion(const GnssConfigSuplVersion suplVersion); - static GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion); static uint32_t convertLppProfile(const GnssConfigLppProfile lppProfile); - static GnssConfigLppProfile convertLppProfile(const uint32_t lppProfile); static uint32_t convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl); static uint32_t convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices); static uint32_t convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask); - static GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask); static uint32_t convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask); - static GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask); static uint32_t convertAGloProt(const GnssConfigAGlonassPositionProtocolMask); static uint32_t convertSuplMode(const GnssConfigSuplModeMask suplModeMask); static void convertSatelliteInfo(std::vector& out, const GnssSvType& in_constellation, const SystemStatusReports& in); + static bool convertToGnssSvIdConfig( + const std::vector& blacklistedSvIds, GnssSvIdConfig& config); + static void convertFromGnssSvIdConfig( + const GnssSvIdConfig& svConfig, GnssConfig& config); + static void convertGnssSvIdMaskToList( + uint64_t svIdMask, std::vector& svIds, + GnssSvId initialSvId, GnssSvType svType); 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(void* powerStateCb); + /* ======== UTILITIES ================================================================== */ + void reportPowerStateIfChanged(); + void savePowerStateCallback(powerStateCallback powerStateCb){ mPowerStateCb = powerStateCb; } + bool getPowerState() { return mPowerOn; } + 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); }; #endif //GNSS_ADAPTER_H diff --git a/gps/gnss/Makefile.am b/gps/gnss/Makefile.am deleted file mode 100644 index c818cae..0000000 --- a/gps/gnss/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -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++11 - -libgnss_la_SOURCES = \ - location_gnss.cpp \ - GnssAdapter.cpp \ - XtraSystemStatusObserver.cpp \ - Agps.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++ $(GPSUTILS_LIBS) $(LOCCORE_LIBS) - -#Create and Install libraries -lib_LTLIBRARIES = libgnss.la diff --git a/gps/gnss/XtraSystemStatusObserver.cpp b/gps/gnss/XtraSystemStatusObserver.cpp index de7d49a..a58f735 100644 --- a/gps/gnss/XtraSystemStatusObserver.cpp +++ b/gps/gnss/XtraSystemStatusObserver.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -49,6 +49,7 @@ #include #include +using namespace loc_util; using namespace loc_core; #ifdef LOG_TAG @@ -56,8 +57,66 @@ using namespace loc_core; #endif #define LOG_TAG "LocSvc_XSSO" -bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) { - mGpsLock = lock; +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")) { + mSystemStatusObsrvr->connectBackhaul(); + } else if (!STRNCMP(data, "disconnectBackhaul")) { + mSystemStatusObsrvr->disconnectBackhaul(); +#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); + } + }; + 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(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; @@ -65,22 +124,41 @@ bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) { stringstream ss; ss << "gpslock"; - ss << " " << lock; - return ( send(LOC_IPC_XTRA, ss.str()) ); + ss << " " << mGpsLock; + string s = ss.str(); + return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) ); } -bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections) { +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"; - ss << " " << mConnections; - return ( send(LOC_IPC_XTRA, ss.str()) ); + 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) { @@ -93,7 +171,8 @@ bool XtraSystemStatusObserver::updateTac(const string& tac) { stringstream ss; ss << "tac"; ss << " " << tac.c_str(); - return ( send(LOC_IPC_XTRA, ss.str()) ); + string s = ss.str(); + return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) ); } bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) { @@ -106,7 +185,8 @@ bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) { stringstream ss; ss << "mncmcc"; ss << " " << mccmnc.c_str(); - return ( send(LOC_IPC_XTRA, ss.str()) ); + string s = ss.str(); + return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) ); } bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) { @@ -119,7 +199,8 @@ bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) { stringstream ss; ss << "xtrathrottle"; ss << " " << (enabled ? 1 : 0); - return ( send(LOC_IPC_XTRA, ss.str()) ); + string s = ss.str(); + return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) ); } inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdated) { @@ -132,41 +213,22 @@ inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdate stringstream ss; ss << "respondStatus" << endl; - (mGpsLock == -1 ? ss : ss << mGpsLock) << endl << mConnections << 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; - return ( send(LOC_IPC_XTRA, ss.str()) ); -} - -void XtraSystemStatusObserver::onReceive(const std::string& data) { - if (!strncmp(data.c_str(), "ping", sizeof("ping") - 1)) { - LOC_LOGd("ping received"); - -#ifdef USE_GLIB - } else if (!strncmp(data.c_str(), "connectBackhaul", sizeof("connectBackhaul") - 1)) { - mSystemStatusObsrvr->connectBackhaul(); - - } else if (!strncmp(data.c_str(), "disconnectBackhaul", sizeof("disconnectBackhaul") - 1)) { - mSystemStatusObsrvr->disconnectBackhaul(); -#endif - - } else if (!strncmp(data.c_str(), "requestStatus", sizeof("requestStatus") - 1)) { - int32_t xtraStatusUpdated = 0; - sscanf(data.c_str(), "%*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); } - }; - mMsgTask->sendMsg(new (nothrow) HandleStatusRequestMsg(*this, xtraStatusUpdated)); - - } else { - LOC_LOGw("unknown event: %s", data.c_str()); - } + string s = ss.str(); + return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) ); } void XtraSystemStatusObserver::subscribe(bool yes) @@ -218,8 +280,11 @@ void XtraSystemStatusObserver::notify(const list& dlist) } inline ~HandleOsObserverUpdateMsg() { - for (auto each : mDataItemList) { - delete each; + for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) { + if (*itor != nullptr) { + delete *itor; + *itor = nullptr; + } } } @@ -231,7 +296,10 @@ void XtraSystemStatusObserver::notify(const list& dlist) { NetworkInfoDataItemBase* networkInfo = static_cast(each); - mXtraSysStatObj->updateConnections(networkInfo->getAllTypes()); + NetworkInfoType* networkHandleInfo = + static_cast(networkInfo->getNetworkHandle()); + mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(), + networkHandleInfo); } break; diff --git a/gps/gnss/XtraSystemStatusObserver.h b/gps/gnss/XtraSystemStatusObserver.h index 6d3e789..3a5259d 100644 --- a/gps/gnss/XtraSystemStatusObserver.h +++ b/gps/gnss/XtraSystemStatusObserver.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -35,63 +35,56 @@ #include using namespace std; +using namespace loc_util; using loc_core::IOsObserver; using loc_core::IDataItemObserver; using loc_core::IDataItemCore; -using loc_util::LocIpc; -class XtraSystemStatusObserver : public IDataItemObserver, public LocIpc{ +class XtraSystemStatusObserver : public IDataItemObserver { public : // constructor & destructor - inline XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask): - mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask), - mGpsLock(-1), mConnections(0), mXtraThrottle(true), mReqStatusReceived(false), - mIsConnectivityStatusKnown (false), mDelayLocTimer(*this) { - subscribe(true); - startListeningNonBlocking(LOC_IPC_HAL); - mDelayLocTimer.start(100 /*.1 sec*/, false); - } + XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask); inline virtual ~XtraSystemStatusObserver() { subscribe(false); - stopListening(); + mIpc.stopNonBlockingListening(); } // IDataItemObserver overrides inline virtual void getName(string& name); virtual void notify(const list& dlist); - bool updateLockStatus(uint32_t lock); - bool updateConnections(uint64_t allConnections); + 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); - -protected: - void onReceive(const std::string& data) override; + bool onStatusRequested(int32_t xtraStatusUpdated); private: IOsObserver* mSystemStatusObsrvr; const MsgTask* mMsgTask; - int32_t mGpsLock; + 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 mSender; class DelayLocTimer : public LocTimer { - XtraSystemStatusObserver& mXSSO; + LocIpcSender& mSender; public: - DelayLocTimer(XtraSystemStatusObserver& xsso) : mXSSO(xsso) {} + DelayLocTimer(LocIpcSender& sender) : mSender(sender) {} void timeOutCallback() override { - mXSSO.send(LOC_IPC_XTRA, "halinit"); + LocIpc::send(mSender, (const uint8_t*)"halinit", sizeof("halinit")); } } mDelayLocTimer; - - bool onStatusRequested(int32_t xtraStatusUpdated); }; #endif diff --git a/gps/gnss/location_gnss.cpp b/gps/gnss/location_gnss.cpp index 21763dd..76839b6 100644 --- a/gps/gnss/location_gnss.cpp +++ b/gps/gnss/location_gnss.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* 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 @@ -36,11 +36,11 @@ static void initialize(); static void deinitialize(); static void addClient(LocationAPI* client, const LocationCallbacks& callbacks); -static void removeClient(LocationAPI* client); +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb); static void requestCapabilities(LocationAPI* client); -static uint32_t startTracking(LocationAPI* client, LocationOptions& options); -static void updateTrackingOptions(LocationAPI* client, uint32_t id, LocationOptions& options); +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); @@ -51,8 +51,14 @@ static void setControlCallbacks(LocationControlCallbacks& controlCallbacks); static uint32_t enable(LocationTechnologyType techType); static void disable(uint32_t id); static uint32_t* gnssUpdateConfig(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); @@ -60,11 +66,20 @@ static void agpsDataConnOpen(AGpsExtType agpsType, const char* apnName, int apnL static void agpsDataConnClosed(AGpsExtType agpsType); static void agpsDataConnFailed(AGpsExtType agpsType); static void getDebugReport(GnssDebugReport& report); -static void updateConnectionStatus(bool connected, int8_t type); +static void updateConnectionStatus(bool connected, int8_t type, bool roaming = false, + NetworkHandle networkHandle = NETWORK_HANDLE_UNKNOWN); +static void getGnssEnergyConsumed(GnssEnergyConsumedCallback energyConsumedCb); +static void enableNfwLocationAccess(bool enable); +static void nfwInit(const NfwCbInfo& cbInfo); +static void getPowerStateChanges(void* powerStateCb); static void odcpiInit(const OdcpiRequestCallback& callback); 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 const GnssInterface gGnssInterface = { sizeof(GnssInterface), initialize, @@ -80,6 +95,10 @@ static const GnssInterface gGnssInterface = { enable, disable, gnssUpdateConfig, + gnssGetConfig, + gnssUpdateSvTypeConfig, + gnssGetSvTypeConfig, + gnssResetSvTypeConfig, gnssDeleteAidingData, gnssUpdateXtraThrottle, injectLocation, @@ -92,6 +111,13 @@ static const GnssInterface gGnssInterface = { updateConnectionStatus, odcpiInit, odcpiInject, + blockCPI, + getGnssEnergyConsumed, + enableNfwLocationAccess, + nfwInit, + getPowerStateChanges, + injectLocationExt, + updateBatteryStatus }; #ifndef DEBUG_X86 @@ -125,10 +151,10 @@ static void addClient(LocationAPI* client, const LocationCallbacks& callbacks) } } -static void removeClient(LocationAPI* client) +static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb) { if (NULL != gGnssAdapter) { - gGnssAdapter->removeClientCommand(client); + gGnssAdapter->removeClientCommand(client, rmClientCb); } } @@ -139,19 +165,22 @@ static void requestCapabilities(LocationAPI* client) } } -static uint32_t startTracking(LocationAPI* client, LocationOptions& options) +static uint32_t startTracking( + LocationAPI* client, TrackingOptions& trackingOptions) { if (NULL != gGnssAdapter) { - return gGnssAdapter->startTrackingCommand(client, options); + return gGnssAdapter->startTrackingCommand(client, trackingOptions); } else { return 0; } } -static void updateTrackingOptions(LocationAPI* client, uint32_t id, LocationOptions& options) +static void updateTrackingOptions( + LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions) { if (NULL != gGnssAdapter) { - gGnssAdapter->updateTrackingOptionsCommand(client, id, options); + gGnssAdapter->updateTrackingOptionsCommand( + client, id, trackingOptions); } } @@ -172,7 +201,7 @@ static void gnssNiResponse(LocationAPI* client, uint32_t id, GnssNiResponse resp static void setControlCallbacks(LocationControlCallbacks& controlCallbacks) { if (NULL != gGnssAdapter) { - return gGnssAdapter->setControlCallbacksCommand(controlCallbacks); + gGnssAdapter->setControlCallbacksCommand(controlCallbacks); } } @@ -188,7 +217,7 @@ static uint32_t enable(LocationTechnologyType techType) static void disable(uint32_t id) { if (NULL != gGnssAdapter) { - return gGnssAdapter->disableCommand(id); + gGnssAdapter->disableCommand(id); } } @@ -201,6 +230,36 @@ static uint32_t* gnssUpdateConfig(GnssConfig config) } } +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) { @@ -265,9 +324,11 @@ static void getDebugReport(GnssDebugReport& report) { } } -static void updateConnectionStatus(bool connected, int8_t type) { +static void updateConnectionStatus(bool connected, int8_t type, + bool roaming, NetworkHandle networkHandle) { if (NULL != gGnssAdapter) { - gGnssAdapter->getSystemStatus()->eventConnectionStatus(connected, type); + gGnssAdapter->getSystemStatus()->eventConnectionStatus( + connected, type, roaming, networkHandle); } } @@ -285,3 +346,47 @@ static void odcpiInject(const Location& 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(void* 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); + } +} diff --git a/gps/gnsspps/Android.mk b/gps/gnsspps/Android.mk index f87b674..ef43979 100644 --- a/gps/gnsspps/Android.mk +++ b/gps/gnsspps/Android.mk @@ -4,6 +4,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libgnsspps +LOCAL_SANITIZE += $(GNSS_SANITIZE) +# activate the following line for debug purposes only, comment out for production +#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG) LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64 LOCAL_MODULE_TAGS := optional diff --git a/gps/gnsspps/Makefile.am b/gps/gnsspps/Makefile.am deleted file mode 100644 index c990be0..0000000 --- a/gps/gnsspps/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -AM_CFLAGS = \ - $(LOCPLA_CFLAGS) \ - $(GPSUTILS_CFLAGS) \ - -I$(WORKSPACE)/system/core/include \ - -I./ - -ACLOCAL_AMFLAGS = -I m4 - -libgnsspps_la_SOURCES = \ - gnsspps.c - -if USE_GLIB -libgnsspps_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ -libgnsspps_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 -libgnsspps_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ -else -libgnsspps_la_CFLAGS = $(AM_CFLAGS) -libgnsspps_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 -libgnsspps_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -endif - -libgnsspps_la_LIBADD = -lstdc++ $(GPSUTILS_LIBS) - -library_include_HEADERS = \ - gnsspps.h - -#Create and Install libraries -lib_LTLIBRARIES = libgnsspps.la - -library_includedir = $(pkgincludedir) -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = gnsspps.pc -EXTRA_DIST = $(pkgconfig_DATA) - - - - diff --git a/gps/gnsspps/configure.ac b/gps/gnsspps/configure.ac deleted file mode 100644 index eb87bc1..0000000 --- a/gps/gnsspps/configure.ac +++ /dev/null @@ -1,70 +0,0 @@ -# configure.ac -- Autoconf script for gps lbs-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 lbs-core package version 1.0.0 -AC_INIT([gnsspps],1.0.0) -# Does not strictly follow GNU Coding standards -AM_INIT_AUTOMAKE([foreign]) -# 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]) - -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 \ - gnsspps.pc - ]) - -AC_OUTPUT diff --git a/gps/gnsspps/gnsspps.c b/gps/gnsspps/gnsspps.c index 70b23f5..b27fd77 100644 --- a/gps/gnsspps/gnsspps.c +++ b/gps/gnsspps/gnsspps.c @@ -35,16 +35,42 @@ #include #include #include +#include +#include "loc_cfg.h" +#include +#include +#include + +#define BILLION_NSEC (1E9) + +typedef struct timespec pps_sync_time; //DRsync kernel timestamp static struct timespec drsyncKernelTs = {0,0}; //DRsync userspace timestamp static struct timespec drsyncUserTs = {0,0}; + +static struct timespec prevDrsyncKernelTs = {0,0}; + //flag to stop fetching timestamp static int isActive = 0; static pps_handle handle; static pthread_mutex_t ts_lock; +static int skipPPSPulseCnt = 0; +static int gnssOutageInSec = 1; +static loc_param_s_type gps_conf_param_table[] = +{ + {"IGNORE_PPS_PULSE_COUNT", &skipPPSPulseCnt, NULL, 'n'}, + {"GNSS_OUTAGE_DURATION", &gnssOutageInSec, NULL, 'n'} +}; + +typedef enum { + KERNEL_REPORTED_CLOCK_BOOTTIME = 0, + KERNEL_REPORTED_CLOCK_REALTIME, + KERNEL_REPORTED_CLOCK_UNKNOWN = 0xfe, + KERNEL_REPORTED_CLOCK_MAX = 0xff +} kernel_reported_time_e; /* checks the PPS source and opens it */ int check_device(char *path, pps_handle *handle) @@ -52,7 +78,7 @@ int check_device(char *path, pps_handle *handle) int ret; /* Try to find the source by using the supplied "path" name */ - ret = open(path, O_RDWR); + ret = open(path, O_RDONLY); if (ret < 0) { LOC_LOGV("%s:%d unable to open device %s", __func__, __LINE__, path); @@ -69,34 +95,205 @@ int check_device(char *path, pps_handle *handle) return 0; } + +/* calculate the time difference between two given times in argument - +** returns the result in timeDifference parametter*/ +static inline void calculate_time_difference(pps_sync_time time1, + pps_sync_time time2, pps_sync_time* timeDifference) +{ + if (time2.tv_nsec < time1.tv_nsec) { + timeDifference->tv_sec = time2.tv_sec - 1 - time1.tv_sec; + timeDifference->tv_nsec = BILLION_NSEC + time2.tv_nsec - time1.tv_nsec; + } else { + timeDifference->tv_sec = time2.tv_sec - time1.tv_sec; + timeDifference->tv_nsec = time2.tv_nsec - time1.tv_nsec; + } +} + +/*add two timespec values and return the result in third resultTime parameter*/ +static inline void pps_sync_time_add(pps_sync_time time1, + pps_sync_time time2, pps_sync_time* resultTime) +{ + if (time2.tv_nsec + time1.tv_nsec >= BILLION_NSEC) { + resultTime->tv_sec = time2.tv_sec + time1.tv_sec + 1; + resultTime->tv_nsec = time2.tv_nsec + time1.tv_nsec - BILLION_NSEC; + } else { + resultTime->tv_sec = time2.tv_sec + time1.tv_sec; + resultTime->tv_nsec = time2.tv_nsec + time1.tv_nsec; + } +} + +#define MAX_REALTIME_OFFSET_DELTA_DIFFERENCE 10 +#define MAX_PPS_KERNEL_TO_USERSPACE_LATENCY 100 /*in milli-second*/ + +static inline double convertTimeToMilliSec(pps_sync_time timeToConvert) +{ + return ((double)(timeToConvert.tv_sec * 1000) + (double)(timeToConvert.tv_nsec * 0.000001)); +} + +/*returnValue: 1 = offsetTime OK, 0 = offsetTime NOT OK*/ +static inline bool isTimeOffsetOk(pps_sync_time offsetTime) +{ + double offsetInMillis = convertTimeToMilliSec(offsetTime); + return (fabs(offsetInMillis) <= MAX_REALTIME_OFFSET_DELTA_DIFFERENCE)? true: false; +} + +/*check whether kernel PPS timestamp is a CLOCK_BOOTTIME or CLOCK_REALTIME*/ +static kernel_reported_time_e get_reported_time_type(pps_sync_time userBootTs, + pps_sync_time userRealTs, + pps_sync_time kernelTs) +{ + double userRealMs, userBootMs, kernelTsMs; + kernel_reported_time_e reportedTime = KERNEL_REPORTED_CLOCK_UNKNOWN; + + userRealMs = convertTimeToMilliSec(userRealTs); + userBootMs = convertTimeToMilliSec(userBootTs); + kernelTsMs = convertTimeToMilliSec(kernelTs); + + if(fabs(userBootMs - kernelTsMs) <= MAX_PPS_KERNEL_TO_USERSPACE_LATENCY) { + reportedTime = KERNEL_REPORTED_CLOCK_BOOTTIME; + } else if (fabs(userRealMs - kernelTsMs) <= MAX_PPS_KERNEL_TO_USERSPACE_LATENCY) { + reportedTime = KERNEL_REPORTED_CLOCK_REALTIME; + } else { + reportedTime = KERNEL_REPORTED_CLOCK_UNKNOWN; + } + + LOC_LOGV("[%s] Detected PPS timestamp type (0:Boot, 1:Real, 0xfe:Unknown):0x%x", + __func__, reportedTime); + + return reportedTime; +} + +/*compute_real_to_boot_time - converts the kernel real time stamp to boot time reference*/ +static int compute_real_to_boot_time(pps_info ppsFetchTime) +{ + int retVal = 0; + /*Offset between REAL_TIME to BOOT_TIME*/ + static pps_sync_time time_offset = {0, 0}; + pps_sync_time drSyncUserRealTs, drSyncUserBootTs; + pps_sync_time deltaRealToBootTime = {0, 0}; + pps_sync_time deltaOffsetTime = {0, 0}; + kernel_reported_time_e ppsTimeType; + + retVal = clock_gettime(CLOCK_BOOTTIME,&drSyncUserBootTs); + if (retVal != 0) { + LOC_LOGE("[%s]Error Reading CLOCK_BOOTTIME", __func__); + retVal = -1; + goto exit0; + } + retVal = clock_gettime(CLOCK_REALTIME,&drSyncUserRealTs); + if (retVal != 0){ + LOC_LOGE("[%s]Error Reading CLOCK_REALTIME", __func__); + retVal = -1; + goto exit0; + } + + ppsTimeType = get_reported_time_type(drSyncUserBootTs, drSyncUserRealTs, ppsFetchTime); + + if (KERNEL_REPORTED_CLOCK_BOOTTIME == ppsTimeType) { + + /*Store PPS kernel time*/ + drsyncKernelTs.tv_sec = ppsFetchTime.tv_sec; + drsyncKernelTs.tv_nsec = ppsFetchTime.tv_nsec; + /*Store User PPS fetch time*/ + drsyncUserTs.tv_sec = drSyncUserBootTs.tv_sec; + drsyncUserTs.tv_nsec = drSyncUserBootTs.tv_nsec; + + LOC_LOGV("[compute_real_to_boot] PPS TimeType CLOCK_BOOTTIME -- report as is"); + retVal = 0; + } else if (KERNEL_REPORTED_CLOCK_REALTIME == ppsTimeType) { + + /* Calculate time difference between REALTIME to BOOT_TIME*/ + calculate_time_difference(drSyncUserRealTs, drSyncUserBootTs, &deltaRealToBootTime); + + /* Calculate the time difference between stored offset and computed one now*/ + calculate_time_difference(time_offset, deltaRealToBootTime, &deltaOffsetTime); + + if ((0 == time_offset.tv_sec && 0 == time_offset.tv_nsec) || + (isTimeOffsetOk(deltaOffsetTime))) { + /* if Time Offset does not change beyond threshold then + ** convert to boot time*/ + drsyncUserTs.tv_sec = drSyncUserBootTs.tv_sec; + drsyncUserTs.tv_nsec = drSyncUserBootTs.tv_nsec; + pps_sync_time_add(ppsFetchTime, deltaRealToBootTime, &drsyncKernelTs); + retVal = 0; + } else { + /*The offset is too high, jump detected in realTime tick, either + ** wall clock changed by user of NTP, skip PPS, re-sync @ next tick + */ + LOC_LOGE("[%s] Jump detected in CLOCK_REALTIME - Offset %ld:%ld", __func__, + deltaOffsetTime.tv_sec, deltaOffsetTime.tv_nsec); + retVal = -1; + } + time_offset.tv_sec = deltaRealToBootTime.tv_sec; + time_offset.tv_nsec = deltaRealToBootTime.tv_nsec; + + LOC_LOGV("[compute_real_to_boot] KernelRealTs %ld:%ld ComputedTs %ld:%ld RealTs %ld:%ld BootTs %ld:%ld Offset %ld:%ld retVal %d ", + ppsFetchTime.tv_sec, ppsFetchTime.tv_nsec, + drsyncKernelTs.tv_sec, drsyncKernelTs.tv_nsec, drSyncUserRealTs.tv_sec, + drSyncUserRealTs.tv_nsec, drsyncUserTs.tv_sec, drsyncUserTs.tv_nsec, + time_offset.tv_sec, time_offset.tv_nsec, retVal); + } else { + LOC_LOGV("[compute_real_to_boot] PPS TimeType Unknown -- KernelTs %ld:%ld userRealTs %ld:%ld userBootTs %ld:%ld", + ppsFetchTime.tv_sec, ppsFetchTime.tv_nsec, + drSyncUserRealTs.tv_sec, drSyncUserRealTs.tv_nsec, + drsyncUserTs.tv_sec, drsyncUserTs.tv_nsec); + retVal = -1; + } + +exit0: + return retVal; + +} + + /* fetches the timestamp from the PPS source */ int read_pps(pps_handle *handle) { struct timespec timeout; pps_info infobuf; int ret; + static bool isFirstPulseReceived = false; + static unsigned int skipPulseCnt = 0; // 3sec timeout timeout.tv_sec = 3; timeout.tv_nsec = 0; - ret = pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,&timeout); + ret = pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf, &timeout); - if (ret < 0 && ret !=-EINTR) - { - LOC_LOGV("%s:%d pps_fetch() error %d", __func__, __LINE__, ret); - return -1; - } + if (ret < 0 && ret !=-EINTR) + { + LOC_LOGV("%s:%d pps_fetch() error %d", __func__, __LINE__, ret); + return -1; + } + if (!isFirstPulseReceived && (skipPPSPulseCnt > 0)) { + skipPulseCnt = skipPPSPulseCnt; + isFirstPulseReceived = true; + LOC_LOGV("%s:%d first pps pulse received %ld (sec) %ld (nsec)", + __func__, __LINE__, infobuf.tv_sec, infobuf.tv_nsec) + }else if (isFirstPulseReceived && (skipPPSPulseCnt > 0) && + ((infobuf.tv_sec - prevDrsyncKernelTs.tv_sec) > gnssOutageInSec)) { + LOC_LOGV("%s:%d long RF outage detected, ignore next %d PPS Pulses", + __func__, __LINE__, skipPPSPulseCnt) + skipPulseCnt = skipPPSPulseCnt; + } + prevDrsyncKernelTs.tv_sec = infobuf.tv_sec; + prevDrsyncKernelTs.tv_nsec = infobuf.tv_nsec; + /* check if this dr sync pulse need to be ignored or not*/ + if (skipPulseCnt > 0) { + LOC_LOGV("%s:%d skip pps count %d, ignoring this pps pulse %ld (sec) %ld (nsec)", + __func__,__LINE__, skipPulseCnt, infobuf.tv_sec, infobuf.tv_nsec); + skipPulseCnt--; + return 0; + } + /* update dr syncpulse time*/ - pthread_mutex_lock(&ts_lock); - drsyncKernelTs.tv_sec = infobuf.tv_sec; - drsyncKernelTs.tv_nsec = infobuf.tv_nsec; - ret = clock_gettime(CLOCK_BOOTTIME,&drsyncUserTs); - pthread_mutex_unlock(&ts_lock); + pthread_mutex_lock(&ts_lock); + + ret = compute_real_to_boot_time(infobuf); + + pthread_mutex_unlock(&ts_lock); - if(ret != 0) - { - LOC_LOGV("%s:%d clock_gettime() error",__func__,__LINE__); - } return 0; } @@ -136,7 +333,7 @@ int initPPS(char *devname) LOC_LOGV("%s:%d Could not find PPS source", __func__, __LINE__); return 0; } - + UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_param_table); pthread_mutex_init(&ts_lock,NULL); pid = pthread_create(&thread,NULL,&thread_handle,NULL); diff --git a/gps/gnsspps/gnsspps.pc.in b/gps/gnsspps/gnsspps.pc.in deleted file mode 100644 index 8931ebd..0000000 --- a/gps/gnsspps/gnsspps.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: gnsspps -Description: QTI GPS gnsspps -Version: @VERSION -Libs: -L${libdir} -lgnsspps -Cflags: -I${includedir}/gnsspps diff --git a/gps/loc-hal.pc.in b/gps/loc-hal.pc.in deleted file mode 100644 index 22d174b..0000000 --- a/gps/loc-hal.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -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.mk b/gps/location/Android.mk index bbd6fbd..2a59541 100644 --- a/gps/location/Android.mk +++ b/gps/location/Android.mk @@ -6,6 +6,9 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := liblocation_api +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_TAGS := optional diff --git a/gps/location/ILocationAPI.h b/gps/location/ILocationAPI.h new file mode 100644 index 0000000..3df6f79 --- /dev/null +++ b/gps/location/ILocationAPI.h @@ -0,0 +1,194 @@ +/* Copyright (c) 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 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(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; +}; + +#endif /* ILOCATIONAPI_H */ diff --git a/gps/location/LocationAPI.cpp b/gps/location/LocationAPI.cpp index 0111a9c..4348c27 100644 --- a/gps/location/LocationAPI.cpp +++ b/gps/location/LocationAPI.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* 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 @@ -25,6 +25,7 @@ * 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 @@ -33,42 +34,64 @@ #include #include #include +#include + +typedef const GnssInterface* (getGnssInterface)(); +typedef const GeofenceInterface* (getGeofenceInterface)(); +typedef const BatchingInterface* (getBatchingInterface)(); + +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 + LocationClientDestroyCbMap; -typedef void* (getLocationInterface)(); typedef std::map LocationClientMap; typedef struct { LocationClientMap clientData; + LocationClientDestroyCbMap destroyClientData; LocationControlAPI* controlAPI; LocationControlCallbacks controlCallbacks; GnssInterface* gnssInterface; GeofenceInterface* geofenceInterface; - FlpInterface* flpInterface; + BatchingInterface* batchingInterface; } LocationAPIData; + static LocationAPIData gData = {}; static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; static bool gGnssLoadFailed = false; -static bool gFlpLoadFailed = false; +static bool gBatchingLoadFailed = false; static bool gGeofenceLoadFailed = false; -static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks) -{ - return (locationCallbacks.gnssLocationInfoCb != nullptr || - locationCallbacks.gnssSvCb != nullptr || - locationCallbacks.gnssNmeaCb != nullptr || - locationCallbacks.gnssMeasurementsCb != nullptr); +template +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 bool isGnssClient(LocationCallbacks& locationCallbacks) { return (locationCallbacks.gnssNiCb != nullptr || locationCallbacks.trackingCb != nullptr || + locationCallbacks.gnssLocationInfoCb != nullptr || + locationCallbacks.engineLocationsInfoCb != nullptr || locationCallbacks.gnssMeasurementsCb != nullptr); } -static bool isFlpClient(LocationCallbacks& locationCallbacks) +static bool isBatchingClient(LocationCallbacks& locationCallbacks) { - return (locationCallbacks.trackingCb != nullptr || - locationCallbacks.batchingCb != nullptr); + return (locationCallbacks.batchingCb != nullptr); } static bool isGeofenceClient(LocationCallbacks& locationCallbacks) @@ -77,32 +100,48 @@ static bool isGeofenceClient(LocationCallbacks& locationCallbacks) locationCallbacks.geofenceStatusCb != nullptr); } -static void* loadLocationInterface(const char* library, const char* name) { - LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name); - if (NULL == library || NULL == name) { - return NULL; - } - getLocationInterface* getter = NULL; - const char *error = NULL; - dlerror(); - void *handle = dlopen(library, RTLD_NOW); - if (NULL == handle || (error = dlerror()) != NULL) { - LOC_LOGW("dlopen for %s failed, error = %s", library, error); - } else { - getter = (getLocationInterface*)dlsym(handle, name); - if ((error = dlerror()) != NULL) { - LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error); - getter = NULL; + +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 (NULL == getter) { - return (void*)getter; - } else { - return (*getter)(); + if ((true == invokeCallback) && (nullptr != destroyCompleteCb)) { + LOC_LOGd("invoke client destroy cb"); + (destroyCompleteCb) (); + LOC_LOGd("finish invoke client destroy cb"); + + 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) { @@ -120,7 +159,8 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) if (isGnssClient(locationCallbacks)) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); @@ -137,21 +177,22 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) } } - if (isFlpClient(locationCallbacks)) { - if (NULL == gData.flpInterface && !gFlpLoadFailed) { - gData.flpInterface = - (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); - if (NULL == gData.flpInterface) { - gFlpLoadFailed = true; - LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); } else { - gData.flpInterface->initialize(); + gData.batchingInterface->initialize(); } } - if (NULL != gData.flpInterface) { - gData.flpInterface->addClient(newLocationAPI, locationCallbacks); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->addClient(newLocationAPI, locationCallbacks); if (!requestedCapabilities) { - gData.flpInterface->requestCapabilities(newLocationAPI); + gData.batchingInterface->requestCapabilities(newLocationAPI); requestedCapabilities = true; } } @@ -160,7 +201,8 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) if (isGeofenceClient(locationCallbacks)) { if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { gData.geofenceInterface = - (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -185,39 +227,79 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks) } void -LocationAPI::destroy() +LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb) { - delete this; -} + bool invokeDestroyCb = false; -LocationAPI::LocationAPI() -{ - LOC_LOGD("LOCATION API CONSTRUCTOR"); -} - -LocationAPI::~LocationAPI() -{ - LOC_LOGD("LOCATION API DESTRUCTOR"); pthread_mutex_lock(&gDataMutex); - auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - if (isGnssClient(it->second) && NULL != gData.gnssInterface) { - gData.gnssInterface->removeClient(it->first); + bool removeFromGnssInf = + (isGnssClient(it->second) && NULL != gData.gnssInterface); + bool removeFromBatchingInf = + (isBatchingClient(it->second) && NULL != gData.batchingInterface); + bool removeFromGeofenceInf = + (isGeofenceClient(it->second) && NULL != gData.geofenceInterface); + bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf); + LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d," + "need %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_LOGe("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask); } - if (isFlpClient(it->second) && NULL != gData.flpInterface) { - gData.flpInterface->removeClient(it->first); + + if (removeFromGnssInf) { + gData.gnssInterface->removeClient(it->first, + onGnssRemoveClientCompleteCb); } - if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) { - gData.geofenceInterface->removeClient(it->first); + if (removeFromBatchingInf) { + gData.batchingInterface->removeClient(it->first, + onBatchingRemoveClientCompleteCb); } + if (removeFromGeofenceInf) { + gData.geofenceInterface->removeClient(it->first, + onGeofenceRemoveClientCompleteCb); + } + gData.clientData.erase(it); + + if ((NULL != destroyCompleteCb) && (false == needToWait)) { + invokeDestroyCb = true; + } } else { LOC_LOGE("%s:%d]: Location API client %p not found in client data", __func__, __LINE__, this); } pthread_mutex_unlock(&gDataMutex); + if (invokeDestroyCb == true) { + (destroyCompleteCb) (); + delete this; + } +} + +LocationAPI::LocationAPI() +{ + LOC_LOGD("LOCATION API CONSTRUCTOR"); +} + +// private destructor +LocationAPI::~LocationAPI() +{ + LOC_LOGD("LOCATION API DESTRUCTOR"); } void @@ -234,7 +316,8 @@ LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) if (isGnssClient(locationCallbacks)) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); @@ -248,27 +331,29 @@ LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) } } - if (isFlpClient(locationCallbacks)) { - if (NULL == gData.flpInterface && !gFlpLoadFailed) { - gData.flpInterface = - (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); - if (NULL == gData.flpInterface) { - gFlpLoadFailed = true; - LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); + if (isBatchingClient(locationCallbacks)) { + if (NULL == gData.batchingInterface && !gBatchingLoadFailed) { + gData.batchingInterface = + (BatchingInterface*)loadLocationInterface("libbatching.so", "getBatchingInterface"); + if (NULL == gData.batchingInterface) { + gBatchingLoadFailed = true; + LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__); } else { - gData.flpInterface->initialize(); + gData.batchingInterface->initialize(); } } - if (NULL != gData.flpInterface) { + if (NULL != gData.batchingInterface) { // either adds new Client or updates existing Client - gData.flpInterface->addClient(this, locationCallbacks); + gData.batchingInterface->addClient(this, locationCallbacks); } } if (isGeofenceClient(locationCallbacks)) { if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { gData.geofenceInterface = - (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); + (GeofenceInterface*)loadLocationInterface("libgeofencing.so", "getGeofenceInterface"); if (NULL == gData.geofenceInterface) { gGeofenceLoadFailed = true; LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); @@ -288,23 +373,17 @@ LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) } uint32_t -LocationAPI::startTracking(LocationOptions& locationOptions) +LocationAPI::startTracking(TrackingOptions& trackingOptions) { uint32_t id = 0; pthread_mutex_lock(&gDataMutex); auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - if (gData.flpInterface != NULL && locationOptions.minDistance > 0) { - id = gData.flpInterface->startTracking(this, locationOptions); - } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) { - id = gData.gnssInterface->startTracking(this, locationOptions); - } else if (gData.flpInterface != NULL) { - id = gData.flpInterface->startTracking(this, locationOptions); - } else if (gData.gnssInterface != NULL) { - id = gData.gnssInterface->startTracking(this, locationOptions); + if (NULL != gData.gnssInterface) { + id = gData.gnssInterface->startTracking(this, trackingOptions); } else { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -323,16 +402,10 @@ LocationAPI::stopTracking(uint32_t id) auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - // we don't know if tracking was started on flp or gnss, so we call stop on both, where - // stopTracking call to the incorrect interface will fail without response back to client if (gData.gnssInterface != NULL) { gData.gnssInterface->stopTracking(this, id); - } - if (gData.flpInterface != NULL) { - gData.flpInterface->stopTracking(this, id); - } - if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -344,22 +417,17 @@ LocationAPI::stopTracking(uint32_t id) } void -LocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions) +LocationAPI::updateTrackingOptions( + uint32_t id, TrackingOptions& trackingOptions) { pthread_mutex_lock(&gDataMutex); auto it = gData.clientData.find(this); if (it != gData.clientData.end()) { - // we don't know if tracking was started on flp or gnss, so we call update on both, where - // updateTracking call to the incorrect interface will fail without response back to client if (gData.gnssInterface != NULL) { - gData.gnssInterface->updateTrackingOptions(this, id, locationOptions); - } - if (gData.flpInterface != NULL) { - gData.flpInterface->updateTrackingOptions(this, id, locationOptions); - } - if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { - LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", + gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions); + } else { + LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", __func__, __LINE__, this); } } else { @@ -371,15 +439,15 @@ LocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions } uint32_t -LocationAPI::startBatching(LocationOptions& locationOptions, BatchingOptions &batchingOptions) +LocationAPI::startBatching(BatchingOptions &batchingOptions) { uint32_t id = 0; pthread_mutex_lock(&gDataMutex); - if (gData.flpInterface != NULL) { - id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions); + if (NULL != gData.batchingInterface) { + id = gData.batchingInterface->startBatching(this, batchingOptions); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -392,10 +460,10 @@ LocationAPI::stopBatching(uint32_t id) { pthread_mutex_lock(&gDataMutex); - if (gData.flpInterface != NULL) { - gData.flpInterface->stopBatching(this, id); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->stopBatching(this, id); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -403,18 +471,14 @@ LocationAPI::stopBatching(uint32_t id) } void -LocationAPI::updateBatchingOptions(uint32_t id, - LocationOptions& locationOptions, BatchingOptions& batchOptions) +LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions) { pthread_mutex_lock(&gDataMutex); - if (gData.flpInterface != NULL) { - gData.flpInterface->updateBatchingOptions(this, - id, - locationOptions, - batchOptions); + if (NULL != gData.batchingInterface) { + gData.batchingInterface->updateBatchingOptions(this, id, batchOptions); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -426,10 +490,10 @@ LocationAPI::getBatchedLocations(uint32_t id, size_t count) { pthread_mutex_lock(&gDataMutex); - if (gData.flpInterface != NULL) { - gData.flpInterface->getBatchedLocations(this, id, count); + if (gData.batchingInterface != NULL) { + gData.batchingInterface->getBatchedLocations(this, id, count); } else { - LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", + LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ", __func__, __LINE__, this); } @@ -537,7 +601,8 @@ LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCall if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) { if (NULL == gData.gnssInterface && !gGnssLoadFailed) { gData.gnssInterface = - (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); + (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); if (NULL == gData.gnssInterface) { gGnssLoadFailed = true; LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); @@ -627,6 +692,21 @@ LocationControlAPI::gnssUpdateConfig(GnssConfig config) 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) { diff --git a/gps/location/LocationAPI.h b/gps/location/LocationAPI.h index 530b1b0..6f5987c 100644 --- a/gps/location/LocationAPI.h +++ b/gps/location/LocationAPI.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* 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 @@ -26,742 +26,12 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LOCATION_H -#define LOCATION_H - -#include -#include -#include -#include - -#define GNSS_NI_REQUESTOR_MAX 256 -#define GNSS_NI_MESSAGE_ID_MAX 2048 -#define GNSS_SV_MAX 64 -#define GNSS_MEASUREMENTS_MAX 64 -#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) - -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 -} 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 -} LocationFlagsBits; - -typedef uint16_t LocationTechnologyMask; -typedef enum { - LOCATION_TECHNOLOGY_GNSS_BIT = (1<<0), // location was calculated using GNSS - LOCATION_TECHNOLOGY_CELL_BIT = (1<<1), // location was calculated using Cell - LOCATION_TECHNOLOGY_WIFI_BIT = (1<<2), // location was calculated using WiFi - LOCATION_TECHNOLOGY_SENSORS_BIT = (1<<3), // location was calculated using Sensors -} LocationTechnologyBits; - -typedef enum { - LOCATION_RELIABILITY_NOT_SET = 0, - LOCATION_RELIABILITY_VERY_LOW, - LOCATION_RELIABILITY_LOW, - LOCATION_RELIABILITY_MEDIUM, - LOCATION_RELIABILITY_HIGH, -} LocationReliability; - -typedef uint32_t GnssLocationInfoFlagMask; -typedef enum { - GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT = (1<<0), // valid altitude mean sea level - GNSS_LOCATION_INFO_DOP_BIT = (1<<1), // valid pdop, hdop, and vdop - GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT = (1<<2), // valid magnetic deviation - GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<3), // valid horizontal reliability - GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<4), // valid vertical reliability - GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // valid elipsode semi major - GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // valid elipsode semi minor - GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<7),// valid accuracy elipsode azimuth -} 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; - -typedef uint32_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) -} LocationCapabilitiesBits; - -typedef enum { - LOCATION_TECHNOLOGY_TYPE_GNSS = 0, -} LocationTechnologyType; - -// Configures how GPS is locked when GPS is disabled (through GnssDisable) -typedef 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 -} 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, -} GnssConfigSuplVersion; - -// LTE Positioning Profile -typedef enum { - GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0, // RRLP on LTE (Default) - GNSS_CONFIG_LPP_PROFILE_USER_PLANE, // LPP User Plane (UP) on LTE - GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE, // LPP_Control_Plane (CP) - GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE, // Both LPP UP and CP -} GnssConfigLppProfile; - -// 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), -} 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, -} 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), -} GnssSvOptionsBits; - -typedef enum { - GNSS_ASSISTANCE_TYPE_SUPL = 0, - GNSS_ASSISTANCE_TYPE_C2K, -} 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), -} GnssMeasurementsAdrStateBits; - -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), -} 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), -} GnssMeasurementsStateBits; - -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), -} 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 -} 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), -} GnssAidingDataSvTypeBits; +#ifndef LOCATIONAPI_H +#define LOCATIONAPI_H -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 struct { - bool deleteAll; // if true, delete all aiding data and ignore other params - GnssAidingDataSv sv; // SV specific aiding data - GnssAidingDataCommon common; // common aiding data -} GnssAidingData; - -typedef struct { - size_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) - LocationTechnologyMask techMask; -} Location; - -typedef struct { - size_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 -} LocationOptions; - -typedef struct { - size_t size; - BatchingMode batchingMode; -} BatchingOptions; - -typedef struct { - size_t size; - BatchingStatus batchingStatus; -} BatchingStatusInfo; - -typedef struct { - size_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 { - size_t size; // set to sizeof(GeofenceInfo) - double latitude; // in degrees - double longitude; // in degrees - double radius; // in meters -} GeofenceInfo; - -typedef struct { - size_t size; // set to sizeof(GeofenceBreachNotification) - size_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 { - size_t size; // set to sizeof(GeofenceBreachNotification) - GeofenceStatusAvailable available; // GEOFENCE_STATUS_AVAILABILE_NO/_YES - LocationTechnologyType techType; // GNSS -} GeofenceStatusNotification; - -typedef struct { - size_t size; // set to sizeof(GnssLocationInfo) - 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 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 -} GnssLocationInfoNotification; - -typedef struct { - size_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; +#include "ILocationAPI.h" -typedef struct { - size_t size; // set to sizeof(GnssSv) - uint16_t svId; // Unique Identifier - GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO) - float cN0Dbhz; // signal strength - float elevation; // elevation of SV (in degrees) - float azimuth; // azimuth of SV (in degrees) - GnssSvOptionsMask gnssSvOptionsMask; // Bitwise OR of GnssSvOptionsBits -} GnssSv; - -typedef struct { - size_t size; // set to sizeof(GnssConfigSetAssistanceServer) - GnssAssistanceType type; // SUPL or C2K - const char* hostName; // null terminated string - uint32_t port; // port of server -} GnssConfigSetAssistanceServer; - -typedef struct { - size_t size; // set to sizeof(GnssMeasurementsData) - GnssMeasurementsDataFlagsMask flags; // bitwise OR of GnssMeasurementsDataFlagsBits - 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; -} GnssMeasurementsData; - -typedef struct { - size_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; -} GnssMeasurementsClock; - -typedef struct { - size_t size; // set to sizeof(GnssSvNotification) - size_t count; // number of SVs in the GnssSv array - GnssSv gnssSvs[GNSS_SV_MAX]; // information on a number of SVs -} GnssSvNotification; - -typedef struct { - size_t size; // set to sizeof(GnssNmeaNotification) - uint64_t timestamp; // timestamp - const char* nmea; // nmea text - size_t length; // length of the nmea text -} GnssNmeaNotification; - -typedef struct { - size_t size; // set to sizeof(GnssMeasurementsNotification) - size_t count; // number of items in GnssMeasurements array - GnssMeasurementsData measurements[GNSS_MEASUREMENTS_MAX]; - GnssMeasurementsClock clock; // clock -} GnssMeasurementsNotification; - -typedef struct { - size_t size; // set to sizeof(GnssConfig) - GnssConfigFlagsMask flags; // bitwise OR of GnssConfigFlagsBits to mark which params are valid - GnssConfigGpsLock gpsLock; - GnssConfigSuplVersion suplVersion; - GnssConfigSetAssistanceServer assistanceServer; - GnssConfigLppProfile lppProfile; - GnssConfigLppeControlPlaneMask lppeControlPlaneMask; - GnssConfigLppeUserPlaneMask lppeUserPlaneMask; - GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask; - GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl; - GnssConfigSuplEmergencyServices suplEmergencyServices; - GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits -} GnssConfig; - -typedef struct { - size_t size; // set to sizeof - bool mValid; - Location mLocation; - double verticalAccuracyMeters; - double speedAccuracyMetersPerSecond; - double bearingAccuracyDegrees; - timespec mUtcReported; -} GnssDebugLocation; - -typedef struct { - size_t size; // set to sizeof - bool mValid; - int64_t timeEstimate; - float timeUncertaintyNs; - float frequencyUncertaintyNsPerSec; -} GnssDebugTime; - -typedef struct { - size_t size; // set to sizeof - uint32_t svid; - GnssSvType constellation; - GnssEphemerisType mEphemerisType; - GnssEphemerisSource mEphemerisSource; - GnssEphemerisHealth mEphemerisHealth; - float ephemerisAgeSeconds; - bool serverPredictionIsAvailable; - float serverPredictionAgeSeconds; -} GnssDebugSatelliteInfo; - -typedef struct { - size_t size; // set to sizeof - GnssDebugLocation mLocation; - GnssDebugTime mTime; - std::vector mSatelliteInfo; -} GnssDebugReport; - -/* Provides the capabilities of the system - capabilities callback is called once soon after createInstance is called */ -typedef std::function capabilitiesCallback; - -/* Used by tracking, batching, and miscellanous APIs - responseCallback is called for every Tracking, Batching API, and Miscellanous API */ -typedef std::function 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 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 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 batchingCallback; - -typedef std::function & 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 gnssLocationInfoCallback; - -/* Used for addGeofences API, optional can be NULL - geofenceBreachCallback is called when any number of geofences have a state change */ -typedef std::function geofenceBreachCallback; - -/* Used for addGeofences API, optional can be NULL - geofenceStatusCallback is called when any number of geofences have a status change */ -typedef std::function geofenceStatusCallback; - -/* Network Initiated request, optional can be NULL - This callback should be responded to by calling gnssNiResponse */ -typedef std::function 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 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 gnssNmeaCallback; - -/* 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 gnssMeasurementsCallback; - -typedef struct { - size_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 - gnssMeasurementsCallback gnssMeasurementsCb; // optional - batchingStatusCallback batchingStatusCb; // optional -} LocationCallbacks; - -class LocationAPI +class LocationAPI : public ILocationAPI { private: LocationAPI(); @@ -773,15 +43,21 @@ public: of instances have been reached */ static LocationAPI* createInstance(LocationCallbacks&); - /* destroy/cleans up the instance, which should be called when LocationAPI object is - no longer needed. LocationAPI* returned from createInstance will no longer valid - after destroy is called */ - void destroy(); + /* 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 */ - void updateCallbacks(LocationCallbacks&); + virtual void updateCallbacks(LocationCallbacks&) override; /* ================================== TRACKING ================================== */ @@ -793,21 +69,21 @@ public: 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 LocationOptions parameter is invalid */ - uint32_t startTracking(LocationOptions&); // returns session id + 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 */ - void stopTracking(uint32_t id); + virtual void stopTracking(uint32_t id) override; - /* updateTrackingOptions changes the LocationOptions of a tracking session associated with id + /* updateTrackingOptions changes the TrackingOptions 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_INVALID_PARAMETER if TrackingOptions parameters are invalid LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */ - void updateTrackingOptions(uint32_t id, LocationOptions&); + virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) override; /* ================================== BATCHING ================================== */ @@ -826,20 +102,20 @@ public: 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 */ - uint32_t startBatching(LocationOptions&, BatchingOptions&); // returns session id + 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 */ - void stopBatching(uint32_t id); + virtual void stopBatching(uint32_t id) override; - /* updateBatchingOptions changes the LocationOptions of a batching session associated with id + /* updateBatchingOptions changes the BatchingOptions 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_INVALID_PARAMETER if BatchingOptions parameters are invalid LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */ - void updateBatchingOptions(uint32_t id, LocationOptions&, BatchingOptions&); + 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. @@ -848,7 +124,7 @@ public: 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 */ - void getBatchedLocations(uint32_t id, size_t count); + virtual void getBatchedLocations(uint32_t id, size_t count) override; /* ================================== GEOFENCE ================================== */ @@ -862,14 +138,14 @@ public: 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 */ - uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*); // returns id array + 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 */ - void removeGeofences(size_t count, uint32_t* ids); + virtual void removeGeofences(size_t count, uint32_t* ids) override; /* modifyGeofences modifies any number of geofences. Caller should delete ids array after modifyGeofences returns. @@ -877,7 +153,7 @@ public: 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 */ - void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options); + 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 @@ -885,14 +161,14 @@ public: collectiveResponseCallback returns: LOCATION_ERROR_SUCCESS if successful LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */ - void pauseGeofences(size_t count, uint32_t* ids); + 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 */ - void resumeGeofences(size_t count, uint32_t* ids); + virtual void resumeGeofences(size_t count, uint32_t* ids) override; /* ================================== GNSS ====================================== */ @@ -901,16 +177,17 @@ public: 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 */ - void gnssNiResponse(uint32_t id, GnssNiResponse response); + virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override; }; typedef struct { size_t size; // set to sizeof(LocationControlCallbacks) responseCallback responseCb; // mandatory collectiveResponseCallback collectiveResponseCb; // mandatory + gnssConfigCallback gnssConfigCb; // optional } LocationControlCallbacks; -class LocationControlAPI +class LocationControlAPI : public ILocationControlAPI { private: LocationControlAPI(); @@ -959,7 +236,22 @@ public: 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 */ - uint32_t* gnssUpdateConfig(GnssConfig config); + virtual uint32_t* gnssUpdateConfig(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 */ + 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. @@ -968,7 +260,7 @@ public: LOCATION_ERROR_SUCCESS if successful LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */ - uint32_t gnssDeleteAidingData(GnssAidingData& data); + virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override; }; -#endif /* LOCATION_H */ +#endif /* LOCATIONAPI_H */ diff --git a/gps/location/LocationAPIClientBase.cpp b/gps/location/LocationAPIClientBase.cpp index 626968c..5a09712 100644 --- a/gps/location/LocationAPIClientBase.cpp +++ b/gps/location/LocationAPIClientBase.cpp @@ -26,7 +26,7 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_NDDEBUG 0 +#define LOG_NDEBUG 0 #define LOG_TAG "LocSvc_APIClientBase" #include @@ -45,7 +45,7 @@ LocationAPIControlClient::LocationAPIControlClient() : pthread_mutex_init(&mMutex, nullptr); for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } memset(&mConfig, 0, sizeof(GnssConfig)); @@ -75,7 +75,7 @@ LocationAPIControlClient::~LocationAPIControlClient() } for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } pthread_mutex_unlock(&mMutex); @@ -142,24 +142,43 @@ void LocationAPIControlClient::locAPIDisable() uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config) { uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; - if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) { - LOC_LOGV("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__); - retVal = LOCATION_ERROR_SUCCESS; - return retVal; - } 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; + } + } + } + pthread_mutex_unlock(&mMutex); + return retVal; +} - memcpy(&mConfig, &config, sizeof(GnssConfig)); +uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask) +{ + uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; + + pthread_mutex_lock(&mMutex); + if (mLocationControlAPI) { - uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config); - LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray); - if (idArray != nullptr) { - if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() != CONFIG_SESSION_ID) { - mRequestQueues[CTRL_REQUEST_CONFIG].reset(CONFIG_SESSION_ID); + 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].push(new GnssUpdateConfigRequest(*this)); + mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this)); retVal = LOCATION_ERROR_SUCCESS; } } @@ -191,12 +210,7 @@ void LocationAPIControlClient::onCtrlCollectiveResponseCb( LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); } } - LocationAPIRequest* request = nullptr; - pthread_mutex_lock(&mMutex); - if (mRequestQueues[CTRL_REQUEST_CONFIG].getSession() == CONFIG_SESSION_ID) { - request = mRequestQueues[CTRL_REQUEST_CONFIG].pop(); - } - pthread_mutex_unlock(&mMutex); + LocationAPIRequest* request = getRequestBySessionArrayPtr(ids); if (request) { request->onCollectiveResponse(count, errors, ids); delete request; @@ -207,13 +221,30 @@ LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t sessi { pthread_mutex_lock(&mMutex); LocationAPIRequest* request = nullptr; - for (int i = 0; i < CTRL_REQUEST_MAX; i++) { - if (i != CTRL_REQUEST_CONFIG && - mRequestQueues[i].getSession() == session) { - request = mRequestQueues[i].pop(); - break; - } + + 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; } @@ -234,7 +265,7 @@ LocationAPIClientBase::LocationAPIClientBase() : pthread_mutex_init(&mMutex, &attr); for (int i = 0; i < REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } } @@ -291,7 +322,7 @@ LocationAPIClientBase::~LocationAPIClientBase() } for (int i = 0; i < REQUEST_MAX; i++) { - mRequestQueues[i].reset(0); + mRequestQueues[i].reset((uint32_t)0); } pthread_mutex_unlock(&mMutex); @@ -299,7 +330,7 @@ LocationAPIClientBase::~LocationAPIClientBase() pthread_mutex_destroy(&mMutex); } -uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& options) +uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options) { uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; pthread_mutex_lock(&mMutex); @@ -335,13 +366,13 @@ void LocationAPIClientBase::locAPIStopTracking() mLocationAPI->stopTracking(session); mTracking = false; } else { - LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session); + LOC_LOGD("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session); } } pthread_mutex_unlock(&mMutex); } -void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& options) +void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options) { pthread_mutex_lock(&mMutex); if (mLocationAPI) { @@ -373,9 +404,8 @@ int32_t LocationAPIClientBase::locAPIGetBatchSize() return mBatchSize; } - -uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t sessionMode, - LocationOptions& locationOptions) +uint32_t LocationAPIClientBase::locAPIStartSession( + uint32_t id, uint32_t sessionMode, TrackingOptions&& options) { uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; pthread_mutex_lock(&mMutex); @@ -389,7 +419,7 @@ uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t session uint32_t batchingSession = 0; if (sessionMode == SESSION_MODE_ON_FIX) { - trackingSession = mLocationAPI->startTracking(locationOptions); + trackingSession = mLocationAPI->startTracking(options); LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession); mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this)); } else { @@ -408,7 +438,12 @@ uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t session break; } - batchingSession = mLocationAPI->startBatching(locationOptions, batchOptions); + // 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)); @@ -465,8 +500,8 @@ uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id) return retVal; } -uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode, - LocationOptions& options) +uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions( + uint32_t id, uint32_t sessionMode, TrackingOptions&& options) { uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; pthread_mutex_lock(&mMutex); @@ -523,13 +558,18 @@ uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t 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(options, batchOptions); + batchingSession = mLocationAPI->startBatching(batchOptions); LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession); mRequestQueues[REQUEST_SESSION].setSession(batchingSession); } else { - mLocationAPI->updateBatchingOptions(batchingSession, options, batchOptions); + mLocationAPI->updateBatchingOptions(batchingSession, batchOptions); } } diff --git a/gps/location/LocationAPIClientBase.h b/gps/location/LocationAPIClientBase.h index 4bd1466..098000c 100644 --- a/gps/location/LocationAPIClientBase.h +++ b/gps/location/LocationAPIClientBase.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* 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 @@ -57,7 +57,8 @@ enum REQUEST_TYPE { enum CTRL_REQUEST_TYPE { CTRL_REQUEST_DELETEAIDINGDATA = 0, CTRL_REQUEST_CONTROL, - CTRL_REQUEST_CONFIG, + CTRL_REQUEST_CONFIG_UPDATE, + CTRL_REQUEST_CONFIG_GET, CTRL_REQUEST_MAX, }; @@ -74,12 +75,13 @@ public: class RequestQueue { public: - RequestQueue(): mSession(0) { + RequestQueue(): mSession(0), mSessionArrayPtr(nullptr) { } virtual ~RequestQueue() { - reset(0); + 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()) { @@ -89,6 +91,10 @@ public: } mSession = session; } + void reset(uint32_t* sessionArrayPtr) { + reset((uint32_t)0); + mSessionArrayPtr = sessionArrayPtr; + } void push(LocationAPIRequest* request) { mQueue.push(request); } @@ -101,8 +107,10 @@ public: return request; } uint32_t getSession() { return mSession; } + uint32_t* getSessionArrayPtr() { return mSessionArrayPtr; } private: uint32_t mSession; + uint32_t* mSessionArrayPtr; std::queue mQueue; }; @@ -114,12 +122,15 @@ public: 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); @@ -130,6 +141,8 @@ public: 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: @@ -167,6 +180,15 @@ public: 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; @@ -187,16 +209,16 @@ public: LocationAPIRequest* getRequestBySession(uint32_t session); // LocationAPI - uint32_t locAPIStartTracking(LocationOptions& options); + uint32_t locAPIStartTracking(TrackingOptions& trackingOptions); void locAPIStopTracking(); - void locAPIUpdateTrackingOptions(LocationOptions& options); + void locAPIUpdateTrackingOptions(TrackingOptions& trackingOptions); int32_t locAPIGetBatchSize(); - uint32_t locAPIStartSession(uint32_t id, uint32_t sessionMode, - LocationOptions& options); + 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, - LocationOptions& options); + 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, @@ -217,6 +239,7 @@ public: inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {} inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {} + inline virtual void onGnssDataCb(GnssDataNotification /*gnssDataNotification*/) {} inline virtual void onGnssMeasurementsCb( GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {} @@ -258,6 +281,8 @@ public: inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {} inline virtual void onGnssNiResponseCb(LocationError /*error*/) {} + inline virtual void onLocationSystemInfoCb(LocationSystemInfo /*locationSystemInfo*/) {} + private: // private inner classes typedef struct { @@ -463,6 +488,7 @@ private: 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); } @@ -480,6 +506,7 @@ private: 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); diff --git a/gps/location/LocationDataTypes.h b/gps/location/LocationDataTypes.h new file mode 100644 index 0000000..17094ab --- /dev/null +++ b/gps/location/LocationDataTypes.h @@ -0,0 +1,1465 @@ +/* Copyright (c) 2018-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 LOCATIONDATATYPES_H +#define LOCATIONDATATYPES_H + +#include +#include +#include +#include +#include + +#define GNSS_NI_REQUESTOR_MAX (256) +#define GNSS_NI_MESSAGE_ID_MAX (2048) +#define GNSS_SV_MAX (176) +#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 +} 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 +} LocationFlagsBits; + +typedef uint16_t LocationTechnologyMask; +typedef enum { + LOCATION_TECHNOLOGY_GNSS_BIT = (1<<0), // location was calculated using GNSS + LOCATION_TECHNOLOGY_CELL_BIT = (1<<1), // location was calculated using Cell + LOCATION_TECHNOLOGY_WIFI_BIT = (1<<2), // location was calculated using WiFi + LOCATION_TECHNOLOGY_SENSORS_BIT = (1<<3), // location was calculated using Sensors +} 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 { + LOCATION_SBAS_CORRECTION_IONO_BIT = (1<<0), // SBAS ionospheric correction is used + LOCATION_SBAS_CORRECTION_FAST_BIT = (1<<1), // SBAS fast correction is used + LOCATION_SBAS_CORRECTION_LONG_BIT = (1<<2), // SBAS long-tem correction is used + LOCATION_SBAS_INTEGRITY_BIT = (1<<3), // SBAS integrity information is used + LOCATION_NAV_CORRECTION_DGNSS_BIT = (1<<4), // Position Report is DGNSS corrected + LOCATION_NAV_CORRECTION_RTK_BIT = (1<<5), // Position Report is RTK corrected + LOCATION_NAV_CORRECTION_PPP_BIT = (1<<6) // Position Report is PPP corrected +} GnssLocationNavSolutionBits; + +typedef uint32_t GnssLocationPosTechMask; +typedef enum { + LOCATION_POS_TECH_DEFAULT_BIT = 0, + LOCATION_POS_TECH_SATELLITE_BIT = (1<<0), + LOCATION_POS_TECH_CELLID_BIT = (1<<1), + LOCATION_POS_TECH_WIFI_BIT = (1<<2), + LOCATION_POS_TECH_SENSORS_BIT = (1<<3), + LOCATION_POS_TECH_REFERENCE_LOCATION_BIT = (1<<4), + LOCATION_POS_TECH_INJECTED_COARSE_POSITION_BIT = (1<<5), + LOCATION_POS_TECH_AFLT_BIT = (1<<6), + LOCATION_POS_TECH_HYBRID_BIT = (1<<7), + LOCATION_POS_TECH_PPE_BIT = (1<<8) +} GnssLocationPosTechBits; + +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 GnssLocationInfoFlagMask; +typedef enum { + GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT = (1<<0), // valid altitude mean sea level + GNSS_LOCATION_INFO_DOP_BIT = (1<<1), // valid pdop, hdop, and vdop + GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT = (1<<2), // valid magnetic deviation + GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT = (1<<3), // valid horizontal reliability + GNSS_LOCATION_INFO_VER_RELIABILITY_BIT = (1<<4), // valid vertical reliability + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT = (1<<5), // valid elipsode semi major + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT = (1<<6), // valid elipsode semi minor + GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT = (1<<7), // valid accuracy elipsode azimuth + GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT = (1<<8), // valid svUsedInPosition, + // numOfMeasReceived + // and measUsageInfo + GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT = (1<<9), // valid navSolutionMask + GNSS_LOCATION_INFO_POS_TECH_MASK_BIT = (1<<10),// valid LocPosTechMask + GNSS_LOCATION_INFO_SV_SOURCE_INFO_BIT = (1<<11),// valid LocSvInfoSource + GNSS_LOCATION_INFO_POS_DYNAMICS_DATA_BIT = (1<<12),// valid position dynamics data + GNSS_LOCATION_INFO_EXT_DOP_BIT = (1<<13),// valid gdop, tdop + GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT = (1<<14),// valid North standard deviation + GNSS_LOCATION_INFO_EAST_STD_DEV_BIT = (1<<15),// valid East standard deviation + GNSS_LOCATION_INFO_NORTH_VEL_BIT = (1<<16),// valid North Velocity + GNSS_LOCATION_INFO_EAST_VEL_BIT = (1<<17),// valid East Velocity + GNSS_LOCATION_INFO_UP_VEL_BIT = (1<<18),// valid Up Velocity + GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT = (1<<19),// valid North Velocity Uncertainty + GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT = (1<<20),// valid East Velocity Uncertainty + GNSS_LOCATION_INFO_UP_VEL_UNC_BIT = (1<<21),// valid Up Velocity Uncertainty + GNSS_LOCATION_INFO_LEAP_SECONDS_BIT = (1<<22),// valid leap seconds + GNSS_LOCATION_INFO_TIME_UNC_BIT = (1<<23),// valid time uncertainty + GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT = (1<<24), // number of SV used in position + GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT = (1<<25), // valid sensor cal confidence + GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT = (1<<26), // valid sensor cal status + GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT = (1<<27), // valid output engine type + GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT = (1<<28), // valid output engine mask +} 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; + +typedef uint32_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), +} LocationCapabilitiesBits; + +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, +} GnssConfigSuplVersion; + +// LTE Positioning Profile +typedef enum { + GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE = 0, // RRLP on LTE (Default) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE, // LPP User Plane (UP) on LTE + GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE, // LPP_Control_Plane (CP) + GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE, // Both LPP UP and CP +} GnssConfigLppProfile; + +// 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), +} 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), +} 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), +} 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 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), +} 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), +} GnssAidingDataSvTypeBits; + +/* 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_I RF Band */ + GNSS_SIGNAL_BEIDOU_B1I = (1<<9), + /** BEIDOU B1C RF Band */ + GNSS_SIGNAL_BEIDOU_B1C = (1<<10), + /** BEIDOU B2_I RF Band */ + GNSS_SIGNAL_BEIDOU_B2I = (1<<11), + /** BEIDOU B2A_I RF Band */ + GNSS_SIGNAL_BEIDOU_B2AI = (1<<12), + /** QZSS L1CA RF Band */ + GNSS_SIGNAL_QZSS_L1CA = (1<<13), + /** QZSS L1S RF Band */ + GNSS_SIGNAL_QZSS_L1S = (1<<14), + /** QZSS L2 RF Band */ + GNSS_SIGNAL_QZSS_L2 = (1<<15), + /** QZSS L5 RF Band */ + GNSS_SIGNAL_QZSS_L5 = (1<<16), + /** SBAS L1 RF Band */ + GNSS_SIGNAL_SBAS_L1 = (1<<17), + /** NAVIC L5 RF Band */ + GNSS_SIGNAL_NAVIC_L5 = (1<<18), + /** BEIDOU B2A_Q RF Band */ + GNSS_SIGNAL_BEIDOU_B2AQ = (1<<19) +} 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, + /**< QZSS 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) +} PositioningEngineBits; + +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 struct { + bool deleteAll; // if true, delete all aiding data and ignore other params + GnssAidingDataSv sv; // SV specific aiding data + GnssAidingDataCommon common; // common aiding data + 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) + LocationTechnologyMask techMask; + LocationSpoofMask spoofMask; +} Location; + +typedef enum { + LOC_REQ_ENGINE_FUSED_BIT = (1<<0), + LOC_REQ_ENGINE_SPE_BIT = (1<<1), + LOC_REQ_ENGINE_PPE_BIT = (1<<2), +} 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_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; + /** GNSS SV ID. + For GPS: 1 to 32 + For GLONASS: 65 to 96. When slot-number to SV ID mapping is unknown, set as 255. + For SBAS: 120 to 151 + For QZSS-L1CA:193 to 197 + For BDS: 201 to 237 + For GAL: 301 to 336 + For NAVIC: 401 to 414 */ + 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 { + /** 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 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 + GnssLocationPosTechMask posTechMask; // Position technology used in computing this fix + 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). 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; +} 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; + +typedef struct { + uint32_t size; // set to sizeof(GnssSv) + uint16_t svId; // Unique Identifier + GnssSvType type; // type of SV (GPS, SBAS, GLONASS, QZSS, BEIDOU, GALILEO) + 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 +} 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 { + uint32_t size; // set to sizeof(GnssMeasurementsData) + GnssMeasurementsDataFlagsMask flags; // bitwise OR of GnssMeasurementsDataFlagsBits + 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]; +} GnssMeasurementsData; + +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; +} 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; // sv id to blacklist +}; +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) +typedef struct { + 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; +} GnssSvIdConfig; + +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; + GnssConfigLppProfile lppProfile; + GnssConfigLppeControlPlaneMask lppeControlPlaneMask; + GnssConfigLppeUserPlaneMask lppeUserPlaneMask; + GnssConfigAGlonassPositionProtocolMask aGlonassPositionProtocolMask; + GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl; + GnssConfigSuplEmergencyServices suplEmergencyServices; + GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits + std::vector blacklistedSvIds; + uint32_t emergencyExtensionSeconds; + + inline bool equals(const GnssConfig& config) { + if (flags == config.flags && + gpsLock == config.gpsLock && + suplVersion == config.suplVersion && + assistanceServer.equals(config.assistanceServer) && + lppProfile == config.lppProfile && + lppeControlPlaneMask == config.lppeControlPlaneMask && + lppeUserPlaneMask == config.lppeUserPlaneMask && + aGlonassPositionProtocolMask == config.aGlonassPositionProtocolMask && + emergencyPdnForEmergencySupl == config.emergencyPdnForEmergencySupl && + suplEmergencyServices == config.suplEmergencyServices && + suplModeMask == config.suplModeMask && + blacklistedSvIds == config.blacklistedSvIds && + emergencyExtensionSeconds == config.emergencyExtensionSeconds) { + 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 { + uint32_t size; // set to sizeof + 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 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; +}; + +/* Provides the capabilities of the system + capabilities callback is called once soon after createInstance is called */ +typedef std::function capabilitiesCallback; + +/* Used by tracking, batching, and miscellanous APIs + responseCallback is called for every Tracking, Batching API, and Miscellanous API */ +typedef std::function 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 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 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 batchingCallback; + +typedef std::function & 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 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 engineLocationsInfoCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceBreachCallback is called when any number of geofences have a state change */ +typedef std::function geofenceBreachCallback; + +/* Used for addGeofences API, optional can be NULL + geofenceStatusCallback is called when any number of geofences have a status change */ +typedef std::function geofenceStatusCallback; + +/* Network Initiated request, optional can be NULL + This callback should be responded to by calling gnssNiResponse */ +typedef std::function 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 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 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 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 gnssMeasurementsCallback; + +/* Provides the current GNSS configuration to the client */ +typedef std::function gnssConfigCallback; + +/* LocationSystemInfoCb is for receiving rare occuring location + system information update. optional, can be NULL. +*/ +typedef std::function locationSystemInfoCallback; + +typedef std::function 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; + +#endif /* LOCATIONDATATYPES_H */ diff --git a/gps/location/Makefile.am b/gps/location/Makefile.am deleted file mode 100644 index 3688cc8..0000000 --- a/gps/location/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -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_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 - -#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 deleted file mode 100644 index 6391d65..0000000 --- a/gps/location/configure.ac +++ /dev/null @@ -1,82 +0,0 @@ -# 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]) -# 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") - -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 deleted file mode 100644 index c7b146a..0000000 --- a/gps/location/location-api.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -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 index 9229052..fb15bea 100644 --- a/gps/location/location_interface.h +++ b/gps/location/location_interface.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017 The Linux Foundation. All rights reserved. +/* 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 @@ -32,21 +32,41 @@ #include #include +/* 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 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); + void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); void (*requestCapabilities)(LocationAPI* client); - uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options); - void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options); + 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)(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); @@ -56,27 +76,31 @@ struct GnssInterface { void (*agpsDataConnClosed)(AGpsExtType agpsType); void (*agpsDataConnFailed)(AGpsExtType agpsType); void (*getDebugReport)(GnssDebugReport& report); - void (*updateConnectionStatus)(bool connected, int8_t type); + void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming, + NetworkHandle networkHandle); void (*odcpiInit)(const OdcpiRequestCallback& callback); 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)(void* powerStateCb); + void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo); + void (*updateBatteryStatus)(bool charging); }; -struct FlpInterface { +struct BatchingInterface { size_t size; void (*initialize)(void); void (*deinitialize)(void); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); - void (*removeClient)(LocationAPI* client); + void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb); void (*requestCapabilities)(LocationAPI* client); - uint32_t (*startTracking)(LocationAPI* client, LocationOptions& options); - void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, LocationOptions& options); - void (*stopTracking)(LocationAPI* client, uint32_t id); - uint32_t (*startBatching)(LocationAPI* client, LocationOptions&, BatchingOptions&); + uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&); void (*stopBatching)(LocationAPI* client, uint32_t id); - void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, LocationOptions&, - BatchingOptions&); + void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&); void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count); - void (*getPowerStateChanges)(void* powerStateCb); }; struct GeofenceInterface { @@ -84,7 +108,7 @@ struct GeofenceInterface { void (*initialize)(void); void (*deinitialize)(void); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); - void (*removeClient)(LocationAPI* client); + 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); diff --git a/gps/pla/Android.mk b/gps/pla/Android.mk index 5d6bb97..a57861d 100644 --- a/gps/pla/Android.mk +++ b/gps/pla/Android.mk @@ -1,6 +1,19 @@ GNSS_CFLAGS := \ -Werror \ - -Wno-undefined-bool-conversion + -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 ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) ifneq ($(BUILD_TINY_ANDROID),true) diff --git a/gps/pla/android/loc_pla.h b/gps/pla/android/loc_pla.h index 74bc2f2..ab8c75e 100644 --- a/gps/pla/android/loc_pla.h +++ b/gps/pla/android/loc_pla.h @@ -40,6 +40,14 @@ extern "C" { #include #include +#include +#include +#include + +#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" diff --git a/gps/pla/oe/loc_pla.h b/gps/pla/oe/loc_pla.h index 6c6dde9..1e3d6c5 100644 --- a/gps/pla/oe/loc_pla.h +++ b/gps/pla/oe/loc_pla.h @@ -30,15 +30,33 @@ #define __LOC_PLA__ #ifdef __cplusplus +#ifndef FEATURE_EXTERNAL_AP #include -#define uptimeMillis android::uptimeMillis +#endif /* FEATURE_EXTERNAL_AP */ +#include +#include +#include + +inline int64_t uptimeMillis() +{ + struct timespec ts; + int64_t time_ms = 0; + clock_gettime(CLOCK_BOOTTIME, &ts); + time_ms += (ts.tv_sec * 1000000000LL); + time_ms += ts.tv_nsec + 500000LL; + return time_ms / 1000000LL; +} extern "C" { #endif +#ifndef FEATURE_EXTERNAL_AP #include #include +#endif /* FEATURE_EXTERNAL_AP */ +#include #include +#include #include #include #ifndef OFF_TARGET @@ -50,6 +68,11 @@ extern "C" { #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" @@ -59,6 +82,16 @@ extern "C" { #define LOC_PATH_XTWIFI_CONF_STR "/etc/xtwifi.conf" #define LOC_PATH_QUIPC_CONF_STR "/etc/quipc.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 */ + #ifdef __cplusplus } #endif /*__cplusplus */ diff --git a/gps/utils/Android.mk b/gps/utils/Android.mk index ec6bf05..88ad487 100644 --- a/gps/utils/Android.mk +++ b/gps/utils/Android.mk @@ -9,6 +9,7 @@ include $(CLEAR_VARS) ## Libs LOCAL_SHARED_LIBRARIES := \ + libdl \ libutils \ libcutils \ liblog \ @@ -46,6 +47,9 @@ LOCAL_HEADER_LIBRARIES := \ liblocation_api_headers LOCAL_MODULE := libgps.utils +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_TAGS := optional diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp index 675664a..64d27cb 100644 --- a/gps/utils/LocIpc.cpp +++ b/gps/utils/LocIpc.cpp @@ -30,8 +30,14 @@ #include #include #include +#include +#include +#include #include -#include "LocIpc.h" +#include +#include + +using namespace std; namespace loc_util { @@ -40,198 +46,369 @@ namespace loc_util { #endif #define LOG_TAG "LocSvc_LocIpc" -#define LOC_MSG_BUF_LEN 8192 -#define LOC_MSG_HEAD "$MSGLEN$" -#define LOC_MSG_ABORT "LocIpcMsg::ABORT" +#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)); \ + } \ + } -class LocIpcRunnable : public LocRunnable { -friend LocIpc; -public: - LocIpcRunnable(LocIpc& locIpc, const std::string& ipcName) - : mLocIpc(locIpc), mIpcName(ipcName) {} - bool run() override { - if (!mLocIpc.startListeningBlocking(mIpcName)) { - LOC_LOGe("listen to socket failed"); +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& 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 false; } -private: - LocIpc& mLocIpc; - const std::string mIpcName; -}; - -bool LocIpc::startListeningNonBlocking(const std::string& name) { - mRunnable = new LocIpcRunnable(*this, name); - std::string threadName("LocIpc-"); - threadName.append(name); - return mThread.start(threadName.c_str(), mRunnable); + return rtv; } +ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr& 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); + } + } + } -bool LocIpc::startListeningBlocking(const std::string& name) { + 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); +} - int fd = socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { - LOC_LOGe("create socket error. reason:%s", strerror(errno)); - return false; +class LocIpcLocalSender : public LocIpcSender { +protected: + shared_ptr 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(make_shared((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))), + mAddr({.sun_family = AF_UNIX, {}}) { + if (mSock != nullptr && mSock->isValid()) { + snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name); + } + } +}; - if ((unlink(name.c_str()) < 0) && (errno != ENOENT)) { - LOC_LOGw("unlink socket error. reason:%s", strerror(errno)); +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& listener, const char* name) : + LocIpcLocalSender(name), LocIpcRecver(listener, *this) { - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name.c_str()); + if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) { + LOC_LOGw("unlink socket error. reason:%s", strerror(errno)); + } - umask(0157); + 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)); + } + } +}; - if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("bind socket error. reason:%s", strerror(errno)); - ::close(fd); - fd = -1; - return false; +class LocIpcInetSender : public LocIpcSender { +protected: + int mSockType; + shared_ptr 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((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); + } + } } - mIpcFd = fd; + unique_ptr getRecver(const shared_ptr& listener) override { + return make_unique(listener, *this, mSock); + } +}; - // inform that the socket is ready to receive message - onListenerReady(); +class LocIpcInetTcpSender : public LocIpcInetSender { +protected: + mutable bool mFirstTime; - ssize_t nBytes = 0; - std::string msg = ""; - std::string abort = LOC_MSG_ABORT; - while (1) { - msg.resize(LOC_MSG_BUF_LEN); - nBytes = ::recvfrom(mIpcFd, (void*)(msg.data()), msg.size(), 0, NULL, NULL); - if (nBytes < 0) { - break; - } else if (nBytes == 0) { - continue; + 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)); + } - if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) { - LOC_LOGi("recvd abort msg.data %s", msg.data()); - break; +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& 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 getLastSender() const override { + return make_unique(static_cast(*this)); + } +}; - if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) { - // short message - msg.resize(nBytes); - onReceive(msg); - } else { - // long message - size_t msgLen = 0; - sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen); - msg.resize(msgLen); - size_t msgLenReceived = 0; - while ((msgLenReceived < msgLen) && (nBytes > 0)) { - nBytes = recvfrom(mIpcFd, (void*)&(msg[msgLenReceived]), - msg.size() - msgLenReceived, 0, NULL, NULL); - msgLenReceived += nBytes; - } - if (nBytes > 0) { - onReceive(msg); - } else { - break; +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& listener, const char* name, + int32_t port) : + LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {} + inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);} +}; - if (mStopRequested) { - mStopRequested = false; - return true; - } else { - LOC_LOGe("cannot read socket. reason:%s", strerror(errno)); - (void)::close(mIpcFd); - mIpcFd = -1; - return false; +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); } -} - -void LocIpc::stopListening() { +public: + inline LocIpcInetUdpRecver(const shared_ptr& listener, const char* name, + int32_t port) : + LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {} - const char *socketName = nullptr; - mStopRequested = true; + inline virtual ~LocIpcInetUdpRecver() {} +}; - if (mRunnable) { - std::string abort = LOC_MSG_ABORT; - socketName = (reinterpret_cast(mRunnable))->mIpcName.c_str(); - send(socketName, abort); - mRunnable = nullptr; +class LocIpcRunnable : public LocRunnable { + bool mAbortCalled; + LocIpc& mLocIpc; + unique_ptr mIpcRecver; +public: + inline LocIpcRunnable(LocIpc& locIpc, unique_ptr& ipcRecver) : + mAbortCalled(false), + mLocIpc(locIpc), + mIpcRecver(std::move(ipcRecver)) {} + inline 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; } - - if (mIpcFd >= 0) { - if (::close(mIpcFd)) { - LOC_LOGe("cannot close socket:%s", strerror(errno)); + inline void abort() { + mAbortCalled = true; + if (mIpcRecver != nullptr) { + mIpcRecver->abort(); } - mIpcFd = -1; } +}; - //delete from the file system at the end - if (socketName) { - unlink(socketName); +bool LocIpc::startNonBlockingListening(unique_ptr& ipcRecver) { + if (ipcRecver != nullptr && ipcRecver->isRecvable()) { + std::string threadName("LocIpc-"); + threadName.append(ipcRecver->getName()); + mRunnable = new LocIpcRunnable(*this, ipcRecver); + return mThread.start(threadName.c_str(), mRunnable); + } else { + LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle"); + return false; } } -bool LocIpc::send(const char name[], const std::string& data) { - return send(name, (const uint8_t*)data.c_str(), data.length()); -} - -bool LocIpc::send(const char name[], const uint8_t data[], uint32_t length) { - - bool result = true; - int fd = ::socket(AF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { - LOC_LOGe("create socket error. reason:%s", strerror(errno)); +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; } - - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name); - - result = sendData(fd, addr, data, length); - - (void)::close(fd); - return result; } +void LocIpc::stopNonBlockingListening() { + if (mRunnable) { + mRunnable->abort(); + mRunnable = nullptr; + } +} -bool LocIpc::sendData(int fd, const sockaddr_un &addr, const uint8_t data[], uint32_t length) { +void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) { + if (ipcRecver.isRecvable()) { + ipcRecver.abort(); + } +} - bool result = true; +bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) { + return sender.sendData(data, length, msgId); +} - if (length <= LOC_MSG_BUF_LEN) { - if (::sendto(fd, data, length, 0, - (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - } - } else { - std::string head = LOC_MSG_HEAD; - head.append(std::to_string(length)); - if (::sendto(fd, head.c_str(), head.length(), 0, - (struct sockaddr*)&addr, sizeof(addr)) < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - } else { - size_t sentBytes = 0; - while(sentBytes < length) { - size_t partLen = length - sentBytes; - if (partLen > LOC_MSG_BUF_LEN) { - partLen = LOC_MSG_BUF_LEN; - } - ssize_t rv = ::sendto(fd, data + sentBytes, partLen, 0, - (struct sockaddr*)&addr, sizeof(addr)); - if (rv < 0) { - LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); - result = false; - break; - } - sentBytes += rv; - } - } - } - return result; +shared_ptr LocIpc::getLocIpcLocalSender(const char* localSockName) { + return make_shared(localSockName); +} +unique_ptr LocIpc::getLocIpcLocalRecver(const shared_ptr& listener, + const char* localSockName) { + return make_unique(listener, localSockName); +} +static void* sLibQrtrHandle = nullptr; +static const char* sLibQrtrName = "libloc_socket.so"; +shared_ptr LocIpc::getLocIpcQrtrSender(int service, int instance) { + typedef shared_ptr (*creator_t) (int, int); + static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName, + "_ZN8loc_util22createLocIpcQrtrSenderEii"); + return (nullptr == creator) ? nullptr : creator(service, instance); +} +unique_ptr LocIpc::getLocIpcQrtrRecver(const shared_ptr& listener, + int service, int instance) { + typedef unique_ptr (*creator_t)(const shared_ptr&, int, int); + static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName, +#ifdef USE_GLIB + "_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii"); +#else + "_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii"); +#endif + return (nullptr == creator) ? nullptr : creator(listener, service, instance); +} +shared_ptr LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) { + return make_shared(serverName, port); +} +unique_ptr LocIpc::getLocIpcInetTcpRecver(const shared_ptr& listener, + const char* serverName, int32_t port) { + return make_unique(listener, serverName, port); +} +shared_ptr LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) { + return make_shared(serverName, port, SOCK_DGRAM); +} +unique_ptr LocIpc::getLocIpcInetUdpRecver(const shared_ptr& listener, + const char* serverName, int32_t port) { + return make_unique(listener, serverName, port); +} +pair, unique_ptr> + LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr& listener, int instance) { + typedef pair, unique_ptr> (*creator_t)(const shared_ptr&, int); + static void* sLibEmuHandle = nullptr; + static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so", + "_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi"); + return (nullptr == creator) ? + make_pair, unique_ptr>(nullptr, nullptr) : + creator(listener, instance); } } diff --git a/gps/utils/LocIpc.h b/gps/utils/LocIpc.h index 364093b..d6f8d1d 100644 --- a/gps/utils/LocIpc.h +++ b/gps/utils/LocIpc.h @@ -27,8 +27,8 @@ * */ -#ifndef __LOC_SOCKET__ -#define __LOC_SOCKET__ +#ifndef __LOC_IPC__ +#define __LOC_IPC__ #include #include @@ -37,33 +37,71 @@ #include #include +using namespace std; + namespace loc_util { + +class LocIpcRecver; class LocIpcSender; +class LocIpcRunnable; + +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 LocIpc { -friend LocIpcSender; public: - inline LocIpc() : mIpcFd(-1), mStopRequested(false), mRunnable(nullptr) {} - inline virtual ~LocIpc() { stopListening(); } + inline LocIpc() : mRunnable(nullptr) {} + inline virtual ~LocIpc() { + stopNonBlockingListening(); + } + + static shared_ptr + getLocIpcLocalSender(const char* localSockName); + static shared_ptr + getLocIpcInetUdpSender(const char* serverName, int32_t port); + static shared_ptr + getLocIpcInetTcpSender(const char* serverName, int32_t port); + static shared_ptr + getLocIpcQrtrSender(int service, int instance); + + static unique_ptr + getLocIpcLocalRecver(const shared_ptr& listener, + const char* localSockName); + static unique_ptr + getLocIpcInetUdpRecver(const shared_ptr& listener, + const char* serverName, int32_t port); + static unique_ptr + getLocIpcInetTcpRecver(const shared_ptr& listener, + const char* serverName, int32_t port); + static unique_ptr + getLocIpcQrtrRecver(const shared_ptr& listener, + int service, int instance); + + static pair, unique_ptr> + getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr& listener, + int instance); // Listen for new messages in current thread. Calling this funciton will - // block current thread. The listening can be stopped by calling stopListening(). - // - // Argument name is the path of the unix local socket to be listened. - // The function will return true on success, and false on failure. - bool startListeningBlocking(const std::string& name); + // 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 stopListening(). - // - // Argument name is the path of the unix local socket to be be listened. - // The function will return true on success, and false on failure. - bool startListeningNonBlocking(const std::string& name); - - // Stop listening to new messages. - void stopListening(); + // The listening can be stopped by calling stopNonBlockingListening(). + bool startNonBlockingListening(unique_ptr& ipcRecver); + void stopNonBlockingListening(); // Send out a message. // Call this function to send a message in argument data to socket in argument name. @@ -71,83 +109,98 @@ public: // 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(const char name[], const std::string& data); - static bool send(const char name[], const uint8_t data[], uint32_t length); - -protected: - // Callback function for receiving incoming messages. - // Override this function in your derived class to process incoming messages. - // For each received message, this callback function will be called once. - // This callback function will be called in the calling thread of startListeningBlocking - // or in the new LocThread created by startListeningNonBlocking. - // - // Argument data contains the received message. You need to parse it. - inline virtual void onReceive(const std::string& /*data*/) {} - - // LocIpc client can overwrite this function to get notification - // when the socket for LocIpc is ready to receive messages. - inline virtual void onListenerReady() {} + static bool send(LocIpcSender& sender, const uint8_t data[], + uint32_t length, int32_t msgId = -1); private: - static bool sendData(int fd, const sockaddr_un& addr, - const uint8_t data[], uint32_t length); - - int mIpcFd; - bool mStopRequested; LocThread mThread; - LocRunnable *mRunnable; + LocIpcRunnable *mRunnable; }; +/* 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: - // Constructor of LocIpcSender class - // - // Argument destSocket contains the full path name of destination socket. - // This class hides generated fd and destination address object from user. - inline LocIpcSender(const char* destSocket): - LocIpcSender(std::make_shared(::socket(AF_UNIX, SOCK_DGRAM, 0)), destSocket) { - if (-1 == *mSocket) { - mSocket = nullptr; - } + virtual ~LocIpcSender() = default; + virtual void informRecverRestarted() {} + 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); } - - // Replicate a new LocIpcSender object with new destination socket. - inline LocIpcSender* replicate(const char* destSocket) { - return (nullptr == mSocket) ? nullptr : new LocIpcSender(mSocket, destSocket); + virtual unique_ptr getRecver(const shared_ptr& listener) { + return nullptr; } +}; - inline ~LocIpcSender() { - if (nullptr != mSocket && mSocket.unique()) { - ::close(*mSocket); - } +class LocIpcRecver { + LocIpcSender& mIpcSender; +protected: + const shared_ptr mDataCb; + inline LocIpcRecver(const shared_ptr& 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 getLastSender() const { + return nullptr; } + virtual void abort() const = 0; + virtual const char* getName() const = 0; +}; - // Send out a message. - // Call this function to send a message - // - // Argument data and length contains the message to be sent out. - // Return true when succeeded - inline bool send(const uint8_t data[], uint32_t length) { - bool rtv = false; - if (nullptr != mSocket && nullptr != data) { - rtv = LocIpc::sendData(*mSocket, mDestAddr, data, length); +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& 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& 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; } - return rtv; } +}; -private: - std::shared_ptr mSocket; - struct sockaddr_un mDestAddr; - - inline LocIpcSender( - const std::shared_ptr& mySocket, const char* destSocket) : mSocket(mySocket) { - if ((nullptr != mSocket) && (-1 != *mSocket) && (nullptr != destSocket)) { - mDestAddr.sun_family = AF_UNIX; - snprintf(mDestAddr.sun_path, sizeof(mDestAddr.sun_path), "%s", destSocket); - } +class SockRecver : public LocIpcRecver { + shared_ptr mSock; +protected: + inline virtual ssize_t recv() const override { + return mSock->recv(*this, mDataCb, 0, nullptr, nullptr); + } +public: + inline SockRecver(const shared_ptr& listener, + LocIpcSender& sender, shared_ptr sock) : + LocIpcRecver(listener, sender), mSock(sock) { + } + inline virtual const char* getName() const override { + return "SockRecver"; } + inline virtual void abort() const override {} }; } -#endif //__LOC_SOCKET__ +#endif //__LOC_IPC__ diff --git a/gps/utils/LocSharedLock.h b/gps/utils/LocSharedLock.h index 7fe6237..a7af35e 100644 --- a/gps/utils/LocSharedLock.h +++ b/gps/utils/LocSharedLock.h @@ -30,10 +30,28 @@ #define __LOC_SHARED_LOCK__ #include +#ifndef FEATURE_EXTERNAL_AP #include +#endif /* FEATURE_EXTERNAL_AP */ #include -// This is a utility created for use cases such that there are more than +#ifdef FEATURE_EXTERNAL_AP +#include + +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 */ + // 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, diff --git a/gps/utils/LocThread.cpp b/gps/utils/LocThread.cpp index c1052cb..568a6bb 100644 --- a/gps/utils/LocThread.cpp +++ b/gps/utils/LocThread.cpp @@ -85,8 +85,8 @@ LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, if (mThandle) { // set thread name char lname[16]; - int len = (sizeof(lname)>sizeof(threadName)) ? - (sizeof(threadName) -1):(sizeof(lname) - 1); + int len = (sizeof(lname) > (strlen(threadName) + 1)) ? + (strlen(threadName)):(sizeof(lname) - 1); memcpy(lname, threadName, len); lname[len] = 0; // set the thread name here diff --git a/gps/utils/Makefile.am b/gps/utils/Makefile.am deleted file mode 100644 index 3801fdd..0000000 --- a/gps/utils/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -ACLOCAL_AMFLAGS = -I m4 - -AM_CFLAGS = -Wundef \ - -MD \ - -Wno-trigraphs \ - -g -O0 \ - -fno-inline \ - -fno-short-enums \ - -fpic \ - -I./ \ - -std=c++11 \ - $(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 \ - loc_misc_utils.h \ - loc_nmea.h \ - gps_extended_c.h \ - gps_extended.h \ - loc_gps.h \ - log_util.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 \ - 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) - -#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 index eaead5c..73a77fd 100644 --- a/gps/utils/MsgTask.cpp +++ b/gps/utils/MsgTask.cpp @@ -74,16 +74,19 @@ void MsgTask::destroy() { } void MsgTask::sendMsg(const LocMsg* msg) const { - if (msg) { + if (msg && this) { msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy); } else { - LOC_LOGE("%s: msg is NULL", __func__); + LOC_LOGE("%s: msg is %p and this is %p", + __func__, msg, this); } } void MsgTask::prerun() { +#ifndef FEATURE_EXTERNAL_AP // make sure we do not run in background scheduling group set_sched_policy(gettid(), SP_FOREGROUND); +#endif /* FEATURE_EXTERNAL_AP */ } bool MsgTask::run() { diff --git a/gps/utils/configure.ac b/gps/utils/configure.ac deleted file mode 100644 index 639f8c4..0000000 --- a/gps/utils/configure.ac +++ /dev/null @@ -1,82 +0,0 @@ -# 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]) -# 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([CUTILS], [libcutils]) -AC_SUBST([CUTILS_CFLAGS]) -AC_SUBST([CUTILS_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 \ - gps-utils.pc - ]) - -AC_OUTPUT diff --git a/gps/utils/gps-utils.pc.in b/gps/utils/gps-utils.pc.in deleted file mode 100644 index a988731..0000000 --- a/gps/utils/gps-utils.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -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 index dc6ad1e..2455629 100644 --- a/gps/utils/gps_extended.h +++ b/gps/utils/gps_extended.h @@ -55,14 +55,19 @@ struct LocPosMode 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) : + 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) { + share_position(sp), powerMode(pMode), + timeBetweenMeasurements(tbm) { memset(credentials, 0, sizeof(credentials)); memset(provider, 0, sizeof(provider)); if (NULL != cred) { @@ -78,7 +83,8 @@ struct LocPosMode recurrence(LOC_GPS_POSITION_RECURRENCE_PERIODIC), min_interval(GPS_DEFAULT_FIX_INTERVAL_MS), preferred_accuracy(50), preferred_time(120000), - share_position(true) { + share_position(true), powerMode(GNSS_POWER_MODE_INVALID), + timeBetweenMeasurements(GPS_DEFAULT_FIX_INTERVAL_MS) { memset(credentials, 0, sizeof(credentials)); memset(provider, 0, sizeof(provider)); } @@ -90,6 +96,8 @@ struct LocPosMode 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); } diff --git a/gps/utils/gps_extended_c.h b/gps/utils/gps_extended_c.h index 5479bec..69a659e 100644 --- a/gps/utils/gps_extended_c.h +++ b/gps/utils/gps_extended_c.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. +/* 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 @@ -35,7 +35,12 @@ #include #include #include -#include + +struct timespec32_t { + uint32_t tv_sec; /* seconds */ + uint32_t tv_nsec; /* and nanoseconds */ +}; + /** * @file @@ -57,6 +62,8 @@ extern "C" { /** 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 @@ -65,20 +72,16 @@ extern "C" { #define ULP_LOCATION_IS_FROM_HYBRID 0x0001 /** Position source is GNSS only */ #define ULP_LOCATION_IS_FROM_GNSS 0x0002 -/** Position source is ZPP only */ -#define ULP_LOCATION_IS_FROM_ZPP 0x0004 /** Position is from a Geofence Breach Event */ -#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0008 +#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0004 /** Position is from Hardware FLP */ -#define ULP_LOCATION_IS_FROM_HW_FLP 0x0010 +#define ULP_LOCATION_IS_FROM_HW_FLP 0x0008 /** Position is from NLP */ -#define ULP_LOCATION_IS_FROM_NLP 0x0020 -/** Position is from PIP */ -#define ULP_LOCATION_IS_FROM_PIP 0x0040 +#define ULP_LOCATION_IS_FROM_NLP 0x0010 /** Position is from external DR solution*/ -#define ULP_LOCATION_IS_FROM_EXT_DR 0X0080 +#define ULP_LOCATION_IS_FROM_EXT_DR 0X0020 /** Raw GNSS position fixes */ -#define ULP_LOCATION_IS_FROM_GNSS_RAW 0X0100 +#define ULP_LOCATION_IS_FROM_GNSS_RAW 0X0040 typedef uint32_t LocSvInfoSource; /** SVinfo source is GNSS/DR */ @@ -95,6 +98,12 @@ typedef uint32_t LocSvInfoSource; #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) @@ -105,6 +114,7 @@ typedef uint32_t LocPosTechMask; #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) enum loc_registration_mask_status { LOC_REGISTRATION_MASK_ENABLED, @@ -117,28 +127,27 @@ typedef enum { 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_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_enum; typedef struct { /** set to sizeof(UlpLocation) */ - size_t size; + uint32_t size; LocGpsLocation gpsLocation; /* Provider indicator for HYBRID or GPS */ uint16_t position_source; LocPosTechMask tech_mask; - /*allows HAL to pass additional information related to the location */ - int rawDataSize; /* in # of bytes */ - void * rawData; - bool is_indoor; - float floor_number; - char map_url[GPS_LOCATION_MAP_URL_SIZE]; - unsigned char map_index[GPS_LOCATION_MAP_INDEX_SIZE]; + bool unpropagatedPosition; } UlpLocation; typedef struct { /** set to sizeof(UlpNmea) */ - size_t size; + uint32_t size; char nmea_str[ULP_MAX_NMEA_STRING_SIZE]; unsigned int len; } UlpNmea; @@ -163,21 +172,47 @@ typedef int16_t AGpsBearerType; #define AGPS_APN_BEARER_IPV6 2 #define AGPS_APN_BEARER_IPV4V6 3 -typedef enum { - AGPS_CB_PRIORITY_LOW = 1, - AGPS_CB_PRIORITY_MED = 2, - AGPS_CB_PRIORITY_HIGH = 3 -} AgpsCbPriority; +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; - AgpsCbPriority cbPriority; + AGpsTypeMask atlType; } AgpsCbInfo; +typedef struct { + void* visibilityControlCb; + void* isInEmergencySession; +} NfwCbInfo; + /** GPS extended callback structure. */ typedef struct { /** set to sizeof(LocGpsCallbacks) */ - size_t size; + uint32_t size; loc_gps_set_capabilities set_capabilities_cb; loc_gps_acquire_wakelock acquire_wakelock_cb; loc_gps_release_wakelock release_wakelock_cb; @@ -201,7 +236,7 @@ typedef struct { /** Represents the status of AGPS. */ typedef struct { /** set to sizeof(AGpsExtStatus) */ - size_t size; + uint32_t size; AGpsExtType type; LocAGpsStatusValue status; @@ -237,7 +272,8 @@ 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_SUPL_SERVER, + LOC_AGPS_MO_SUPL_SERVER } LocServerType; typedef enum loc_position_mode_type { @@ -273,7 +309,7 @@ typedef enum loc_position_mode_type { #define GPS_DEFAULT_FIX_INTERVAL_MS 1000 /** Flags to indicate which values are valid in a GpsLocationExtended. */ -typedef uint32_t GpsLocationExtendedFlags; +typedef uint64_t GpsLocationExtendedFlags; /** GpsLocationExtended has valid pdop, hdop, vdop. */ #define GPS_LOCATION_EXTENDED_HAS_DOP 0x0001 /** GpsLocationExtended has valid altitude mean sea level. */ @@ -312,8 +348,49 @@ typedef uint32_t GpsLocationExtendedFlags; #define GPS_LOCATION_EXTENDED_HAS_GPS_TIME 0x20000 /** GpsLocationExtended has Extended Dilution of Precision */ #define GPS_LOCATION_EXTENDED_HAS_EXT_DOP 0x40000 -/** GpsLocationExtended has Elapsed Time */ -#define GPS_LOCATION_EXTENDED_HAS_ELAPSED_TIME 0x80000 +/** 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 typedef uint32_t LocNavSolutionMask; /* Bitmask to specify whether SBAS ionospheric correction is used */ @@ -324,6 +401,14 @@ typedef uint32_t LocNavSolutionMask; #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) typedef uint32_t LocPosDataMask; /* Bitmask to specify whether Navigation data has Forward Acceleration */ @@ -336,10 +421,29 @@ typedef uint32_t LocPosDataMask; #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 SBAS_SV_PRN_MIN 33 +#define SBAS_SV_PRN_MAX 64 #define GLO_SV_PRN_MIN 65 #define GLO_SV_PRN_MAX 96 #define QZSS_SV_PRN_MIN 193 @@ -348,17 +452,8 @@ typedef uint32_t LocPosDataMask; #define BDS_SV_PRN_MAX 235 #define GAL_SV_PRN_MIN 301 #define GAL_SV_PRN_MAX 336 - -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 NAVIC_SV_PRN_MIN 401 +#define NAVIC_SV_PRN_MAX 414 typedef enum { LOC_RELIABILITY_NOT_SET = 0, @@ -368,8 +463,14 @@ typedef enum { 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 timespec apTimeStamp; + struct timespec32_t apTimeStamp; /*boottime received from pps-ktimer*/ float apTimeStampUncertaintyMs; /* timestamp uncertainty in milli seconds */ @@ -381,22 +482,55 @@ typedef struct { 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 { @@ -434,12 +568,143 @@ typedef struct { 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) + +/** GNSS Signal Type and RF Band */ +typedef uint32_t GnssSignalTypeMask; +/** GPS L1CA Signal */ +#define GNSS_SIGNAL_GPS_L1CA ((GnssSignalTypeMask)0x00000001ul) +/** GPS L1C Signal */ +#define GNSS_SIGNAL_GPS_L1C ((GnssSignalTypeMask)0x00000002ul) +/** GPS L2 RF Band */ +#define GNSS_SIGNAL_GPS_L2 ((GnssSignalTypeMask)0x00000004ul) +/** GPS L5 RF Band */ +#define GNSS_SIGNAL_GPS_L5 ((GnssSignalTypeMask)0x00000008ul) +/** GLONASS G1 (L1OF) RF Band */ +#define GNSS_SIGNAL_GLONASS_G1 ((GnssSignalTypeMask)0x00000010ul) +/** GLONASS G2 (L2OF) RF Band */ +#define GNSS_SIGNAL_GLONASS_G2 ((GnssSignalTypeMask)0x00000020ul) +/** GALILEO E1 RF Band */ +#define GNSS_SIGNAL_GALILEO_E1 ((GnssSignalTypeMask)0x00000040ul) +/** GALILEO E5A RF Band */ +#define GNSS_SIGNAL_GALILEO_E5A ((GnssSignalTypeMask)0x00000080ul) +/** GALILEO E5B RF Band */ +#define GNSS_SIGNAL_GALILIEO_E5B ((GnssSignalTypeMask)0x00000100ul) +/** BEIDOU B1_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B1I ((GnssSignalTypeMask)0x00000200ul) +/** BEIDOU B1C RF Band */ +#define GNSS_SIGNAL_BEIDOU_B1C ((GnssSignalTypeMask)0x00000400ul) +/** BEIDOU B2_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2I ((GnssSignalTypeMask)0x00000800ul) +/** BEIDOU B2A_I RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2AI ((GnssSignalTypeMask)0x00001000ul) +/** QZSS L1CA RF Band */ +#define GNSS_SIGNAL_QZSS_L1CA ((GnssSignalTypeMask)0x00002000ul) +/** QZSS L1S RF Band */ +#define GNSS_SIGNAL_QZSS_L1S ((GnssSignalTypeMask)0x00004000ul) +/** QZSS L2 RF Band */ +#define GNSS_SIGNAL_QZSS_L2 ((GnssSignalTypeMask)0x00008000ul) +/** QZSS L5 RF Band */ +#define GNSS_SIGNAL_QZSS_L5 ((GnssSignalTypeMask)0x00010000ul) +/** SBAS L1 RF Band */ +#define GNSS_SIGNAL_SBAS_L1 ((GnssSignalTypeMask)0x00020000ul) +/** NAVIC L5 RF Band */ +#define GNSS_SIGNAL_NAVIC_L5 ((GnssSignalTypeMask)0x00040000ul) +/** BEIDOU B2A_Q RF Band */ +#define GNSS_SIGNAL_BEIDOU_B2AQ ((GnssSignalTypeMask)0x00080000ul) + +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; + /** GNSS SV ID. + For GPS: 1 to 32 + For GLONASS: 65 to 96. When slot-number to SV ID mapping is unknown, set as 255. + For SBAS: 120 to 151 + For QZSS-L1CA:193 to 197 + For BDS: 201 to 237 + For GAL: 301 to 336 */ + 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; + + /** Represents gps location extended. */ typedef struct { /** set to sizeof(GpsLocationExtended) */ - size_t size; + uint32_t size; /** Contains GpsLocationExtendedFlags bits. */ - uint32_t flags; + uint64_t flags; /** Contains the Altitude wrt mean sea level */ float altitudeMeanSeaLevel; /** Contains Position Dilusion of Precision. */ @@ -470,6 +735,8 @@ typedef struct { 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 */ @@ -477,13 +744,75 @@ typedef struct { /** SV Info source used in computing this fix */ LocSvInfoSource sv_source; /** Body Frame Dynamics: 4wayAcceleration and pitch set with validity */ - LocPositionDynamics bodyFrameData; + GnssLocationPositionDynamics bodyFrameData; /** GPS Time */ GPSTimeStruct gpsTime; - /** Elapsed Time */ - int64_t elapsedTime; + 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; } GpsLocationExtended; enum loc_sess_status { @@ -492,6 +821,13 @@ enum loc_sess_status { LOC_SESS_FAILURE }; +// 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 */ @@ -512,6 +848,20 @@ typedef uint32_t NmeaSentenceTypesMask; #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 */ + // 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 | \ @@ -519,7 +869,12 @@ typedef uint32_t NmeaSentenceTypesMask; 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_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, @@ -583,8 +938,8 @@ enum loc_api_adapter_event_index { 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_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 @@ -594,6 +949,12 @@ enum loc_api_adapter_event_index { 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_EVENT_MAX }; @@ -630,7 +991,12 @@ enum loc_api_adapter_event_index { #define LOC_API_ADAPTER_BIT_POSITION_INJECTION_REQUEST (1< GnssSvTypeConfigCallback; + /* * Represents the status of AGNSS augmented to support IPv4. */ struct AGnssExtStatusIpV4 { - AGpsExtType type; - LocAGpsStatusValue status; + AGpsExtType type; + LocApnTypeMask apnTypeMask; + LocAGpsStatusValue status; /* * 32-bit IPv4 address. */ - uint32_t ipV4Addr; + uint32_t ipV4Addr; }; /* * Represents the status of AGNSS augmented to support IPv6. */ struct AGnssExtStatusIpV6 { - AGpsExtType type; - LocAGpsStatusValue status; + AGpsExtType type; + LocApnTypeMask apnTypeMask; + LocAGpsStatusValue status; /* * 128-bit IPv6 address. */ - uint8_t ipV6Addr[16]; + 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; + /* ODCPI Request Info */ enum OdcpiRequestType { ODCPI_REQUEST_TYPE_START, ODCPI_REQUEST_TYPE_STOP }; struct OdcpiRequestInfo { - size_t size; + uint32_t size; OdcpiRequestType type; uint32_t tbfMillis; bool isEmergencyMode; @@ -1318,6 +2247,12 @@ typedef std::function OdcpiRequestCallbac */ typedef void (*AgnssStatusIpV4Cb)(AGnssExtStatusIpV4 status); +/* +* Callback with NFW information. +*/ +typedef void(*NfwStatusCb)(GnssNfwNotification notification); +typedef bool(*IsInEmergencySession)(void); + /* * Callback with AGNSS(IpV6) status information. * @@ -1332,8 +2267,21 @@ typedef void (*LocAgpsOpenResultCb)(bool isSuccess, AGpsExtType agpsType, const typedef void (*LocAgpsCloseResultCb)(bool isSuccess, AGpsExtType agpsType, void* userDataPtr); /* Shared resources of LocIpc */ -#define LOC_IPC_HAL "/dev/socket/location/socket_hal" -#define LOC_IPC_XTRA "/dev/socket/location/xtra/socket_xtra" +#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" + +typedef uint64_t NetworkHandle; +#define NETWORK_HANDLE_UNKNOWN ~0 +#define MAX_NETWORK_HANDLES 10 #ifdef __cplusplus } diff --git a/gps/utils/linked_list.h b/gps/utils/linked_list.h index a85f09a..0b33ecb 100644 --- a/gps/utils/linked_list.h +++ b/gps/utils/linked_list.h @@ -50,6 +50,8 @@ typedef enum /**< 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; /*=========================================================================== diff --git a/gps/utils/loc_cfg.cpp b/gps/utils/loc_cfg.cpp index e646ea8..8baf8ca 100644 --- a/gps/utils/loc_cfg.cpp +++ b/gps/utils/loc_cfg.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -57,14 +57,15 @@ /* Parameter data */ static uint32_t DEBUG_LEVEL = 0xff; static uint32_t TIMESTAMP = 0; -static uint32_t LOC_MODEM_EMULATOR = 0; +static uint32_t DATUM_TYPE = 0; +static bool sVendorEnhanced = true; /* Parameter spec table */ static const loc_param_s_type loc_param_table[] = { {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'}, {"TIMESTAMP", &TIMESTAMP, NULL, 'n'}, - {"LOC_MODEM_EMULATOR", &LOC_MODEM_EMULATOR, NULL, 'n'}, + {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'}, }; static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type); @@ -87,21 +88,34 @@ 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; -bool isXtraDaemonEnabled() { - bool enabled = property_get_bool("persist.sys.xtra-daemon.enabled", false); - LOC_LOGe("xtra-daemon enabled: %d\n", enabled); - return enabled; +bool isVendorEnhanced() { + return sVendorEnhanced; +} +void setVendorEnhanced(bool vendorEnhanced) { + sVendorEnhanced = vendorEnhanced; } /*=========================================================================== -FUNCTION loc_modem_emulator_enabled +FUNCTION loc_get_datum_type DESCRIPTION - Provides access to Modem Emulator config item. + get datum type + +PARAMETERS: + N/A + +DEPENDENCIES + N/A + +RETURN VALUE + DATUM TYPE + +SIDE EFFECTS + N/A ===========================================================================*/ -uint32_t loc_modem_emulator_enabled() +int loc_get_datum_type() { - return LOC_MODEM_EMULATOR; + return DATUM_TYPE; } /*=========================================================================== @@ -147,7 +161,7 @@ int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* else { strlcpy((char*) config_entry->param_ptr, config_value->param_str_value, - LOC_MAX_PARAM_STRING + 1); + LOC_MAX_PARAM_STRING); } /* Log INI values */ LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__, @@ -446,19 +460,18 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta #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_GTP_AP_CELL_BASIC LOC_FEATURE_MASK_GTP_CELL_BASIC -#define LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM LOC_FEATURE_MASK_GTP_CELL_PREMIUM #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_WAA_PREMIUM 0x200 #define LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC 0X400 -#define LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM 0X800 #define LOC_FEATURE_MASK_ODCPI 0x1000 #define LOC_FEATURE_MASK_FREE_WIFI_SCAN_INJECT 0x2000 #define LOC_FEATURE_MASK_SUPL_WIFI 0x4000 @@ -473,17 +486,18 @@ typedef struct { 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_cell_proc[LOC_MAX_PARAM_STRING]; + char feature_gtp_mode[LOC_MAX_PARAM_STRING]; char feature_gtp_waa[LOC_MAX_PARAM_STRING]; - char feature_gtp_cell[LOC_MAX_PARAM_STRING]; - char feature_gtp_wifi[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 */ @@ -496,9 +510,7 @@ static const loc_param_s_type gps_conf_parameter_table[] = { /* location feature conf, e.g.: izat.conf feature mode table*/ static const loc_param_s_type loc_feature_conf_table[] = { - {"GTP_CELL_PROC", &conf.feature_gtp_cell_proc, NULL, 's'}, - {"GTP_CELL", &conf.feature_gtp_cell, NULL, 's'}, - {"GTP_WIFI", &conf.feature_gtp_wifi, NULL, 's'}, + {"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'}, @@ -509,15 +521,18 @@ static const loc_param_s_type loc_feature_conf_table[] = { /* 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'}, - {"BASEBAND", &conf.baseband, NULL, 's'}, - {"HARDWARE_TYPE", &conf.auto_platform, NULL, 's'}, + {"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'}, }; /*=========================================================================== @@ -553,17 +568,17 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p 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; + 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]; - char autoplatform_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; - char config_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_ap_cell[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] = "--"; @@ -580,7 +595,6 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p //Form argument strings strlcat(arg_gtp_waa, LOC_FEATURE_GTP_WAA, LOC_PROCESS_MAX_ARG_STR_LENGTH-3); - strlcat(arg_gtp_ap_cell, LOC_FEATURE_GTP_AP_CELL, 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); @@ -591,86 +605,42 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p 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_WIFI - if(strcmp(conf.feature_gtp_wifi, "DISABLED") == 0) { - LOC_LOGD("%s:%d]: GTP WIFI DISABLED", __func__, __LINE__); + //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_wifi, "BASIC") == 0) { - LOC_LOGD("%s:%d]: Setting GTP WIFI to mode: BASIC", __func__, __LINE__); - loc_service_mask |= LOC_FEATURE_MASK_GTP_WIFI_BASIC; + 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; } - //conf file has a garbage value - else { - LOC_LOGE("%s:%d]: Unrecognized value for GTP WIFI Mode."\ - " Setting GTP WIFI to default mode: BASIC", __func__, __LINE__); + 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; } - - //Set service mask for GTP_CELL - //Using a temp variable here to indicate wheter GTP cell is - //enabled on the AP or modem. This variable will be used in - //further checks below. An alternative was to compare the - //string again in each place which would've been more expensive - if(strcmp(conf.feature_gtp_cell_proc, "AP") == 0) { - gtp_cell_ap_enabled = 1; - } - - if(strcmp(conf.feature_gtp_cell, "PREMIUM") == 0) { - LOC_LOGE("%s:%d]: Error: location feature GTP CELL does not support PREMIUM mode" \ - " available modes are BASIC and DISABLED. Starting feature in BASIC mode", - __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } - } - else if(strcmp(conf.feature_gtp_cell, "BASIC") == 0) { - LOC_LOGD("%s:%d]: Setting GTP CELL to mode: BASIC", __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } - } - else if(strcmp(conf.feature_gtp_cell, "DISABLED") == 0) { - LOC_LOGD("%s:%d]: GTP CELL DISABLED", __func__, __LINE__); - } //conf file has a garbage value else { - LOC_LOGE("%s:%d]: Unrecognized value for GTP CELL Mode." \ - " Setting GTP CELL to default mode: BASIC", __func__, __LINE__); - if(gtp_cell_ap_enabled) { - loc_service_mask |= LOC_FEATURE_MASK_GTP_AP_CELL_BASIC; - } - else { - loc_service_mask |= LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC; - } + 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, "PREMIUM") == 0) { - LOC_LOGE("%s:%d]: Error: location feature GTP WAA does not support PREMIUM mode" \ - " available modes are BASIC and DISABLED. Starting feature in BASIC mode", - __func__, __LINE__); - loc_service_mask |= LOC_FEATURE_MASK_GTP_WAA_BASIC; - } - else 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; + 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__); + 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__); + LOC_LOGE("%s:%d]: Unrecognized value for GTP WAA Mode."\ + " Setting GTP WAA to default mode: DISABLED", __func__, __LINE__); } //Set service mask for SAP @@ -682,6 +652,9 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p 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__); + } else if(strcmp(conf.feature_sap, "DISABLED") == 0) { LOC_LOGD("%s:%d]: Setting SAP to mode: DISABLED", __func__, __LINE__); } @@ -808,18 +781,19 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p 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) { + !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 (strcmp(conf.proc_name, "xtra-daemon") == 0 && !isXtraDaemonEnabled()) { - LOC_LOGE("%s:%d]: Process xtra-daemon is disabled via property", - __func__, __LINE__); - child_proc[j].proc_status = DISABLED_FROM_CONF; + 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; } @@ -844,18 +818,15 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p child_proc[j].num_groups = 0; ngroups = loc_util_split_string(conf.group_list, split_strings, MAX_NUM_STRINGS, ' '); -#ifdef __ANDROID__ for(i=0; ipw_gid; + 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("%s:%d]:Group %s = %d matches child_group: %d\n", - __func__, __LINE__, split_strings[i], - pwd->pw_gid,child_proc[j].group_list[i]); + LOC_LOGd("Group %s = %d", split_strings[i], grp->gr_gid); } } -#endif + 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))) { @@ -884,6 +855,34 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } + // 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))) { @@ -936,10 +935,19 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } } + 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) && - (child_proc[j].proc_status != DISABLED_FROM_CONF)) { + (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 @@ -949,8 +957,7 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p i = 0; char* temp_arg = ('/' == child_proc[j].name[0][0]) ? (strrchr(child_proc[j].name[0], '/') + 1) : child_proc[j].name[0]; - i++; - strlcpy (child_proc[j].args[i], temp_arg, sizeof (child_proc[j].args[i])); + strlcpy (child_proc[j].args[i++], temp_arg, sizeof (child_proc[j].args[i++])); if(conf.premium_feature) { if(conf.loc_feature_mask & loc_service_mask) { @@ -982,79 +989,19 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p } 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_AP_CELL_BASIC){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_basic, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - 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); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_AP_CELL_PREMIUM){ - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - 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); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_BASIC) { + 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); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - } - else if(loc_service_mask & LOC_FEATURE_MASK_GTP_MODEM_CELL_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_modem_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_premium, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); } else { - strlcpy(child_proc[j].args[i++], arg_gtp_ap_cell, - LOC_PROCESS_MAX_ARG_STR_LENGTH); - strlcpy(child_proc[j].args[i++], arg_disabled, - LOC_PROCESS_MAX_ARG_STR_LENGTH); 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_GTP_WAA_BASIC | LOC_FEATURE_MASK_GTP_WAA_PREMIUM)) { - 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 if(loc_service_mask & LOC_FEATURE_MASK_GTP_WAA_PREMIUM) { - strlcpy(child_proc[j].args[i++], arg_gtp_waa, - 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_waa, - 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) { @@ -1077,6 +1024,22 @@ int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_p 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 #define LOC_MAX_PARAM_NAME 80 -#define LOC_MAX_PARAM_STRING 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" @@ -72,19 +72,20 @@ *============================================================================*/ typedef struct { - const char *param_name; - void *param_ptr; - uint8_t *param_set; /* indicate value set by config file */ - char param_type; /* 'n' for number, - 's' for string, - 'f' for double */ + 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_FROM_CONF, + DISABLED_VIA_VENDOR_ENHANCED_CHECK } loc_process_e_status; typedef struct { @@ -112,6 +113,8 @@ extern "C" { * MODULE EXPORTED FUNCTIONS * *============================================================================*/ +bool isVendorEnhanced(); +void setVendorEnhanced(bool vendorEnhanced); void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table, uint32_t table_length); @@ -132,9 +135,7 @@ extern const char LOC_PATH_QUIPC_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); - -uint32_t loc_modem_emulator_enabled(); - +int loc_get_datum_type(); #ifdef __cplusplus } #endif diff --git a/gps/utils/loc_gps.h b/gps/utils/loc_gps.h index 5e915a3..eae7383 100644 --- a/gps/utils/loc_gps.h +++ b/gps/utils/loc_gps.h @@ -100,6 +100,19 @@ typedef uint16_t LocGpsLocationFlags; #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 + +/** 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. */ @@ -142,13 +155,18 @@ typedef uint16_t LocGpsAidingData; #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 @@ -530,9 +548,11 @@ typedef uint8_t LocGnssConstellationType; /** Represents a location. */ typedef struct { /** set to sizeof(LocGpsLocation) */ - size_t size; + 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. */ diff --git a/gps/utils/loc_misc_utils.cpp b/gps/utils/loc_misc_utils.cpp index b7c8406..70fdbc3 100644 --- a/gps/utils/loc_misc_utils.cpp +++ b/gps/utils/loc_misc_utils.cpp @@ -30,6 +30,7 @@ #define LOG_TAG "LocSvc_misc_utils" #include #include +#include #include #include #include @@ -112,3 +113,33 @@ void loc_util_trim_space(char *org_string) 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; +} diff --git a/gps/utils/loc_misc_utils.h b/gps/utils/loc_misc_utils.h index 7d66d84..fad1b6d 100644 --- a/gps/utils/loc_misc_utils.h +++ b/gps/utils/loc_misc_utils.h @@ -92,6 +92,34 @@ 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); + #ifdef __cplusplus } #endif diff --git a/gps/utils/loc_nmea.cpp b/gps/utils/loc_nmea.cpp index 558dc65..24197ff 100644 --- a/gps/utils/loc_nmea.cpp +++ b/gps/utils/loc_nmea.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* 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 @@ -33,24 +33,87 @@ #include #include #include +#include #define GLONASS_SV_ID_OFFSET 64 +#define QZSS_SV_ID_OFFSET (-192) +#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 // GNSS system id according to NMEA spec #define SYSTEM_ID_GPS 1 #define SYSTEM_ID_GLONASS 2 #define SYSTEM_ID_GALILEO 3 -// Extended systems -#define SYSTEM_ID_BEIDOU 4 +#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]; LocGnssConstellationType svType; - uint32_t mask; + uint64_t mask; uint32_t svCount; + uint32_t totalSvUsedCount; uint32_t svIdOffset; uint32_t signalId; uint32_t systemId; @@ -58,21 +121,259 @@ typedef struct loc_nmea_sv_meta_s typedef struct loc_sv_cache_info_s { - uint32_t gps_used_mask; - uint32_t glo_used_mask; - uint32_t gal_used_mask; - uint32_t qzss_used_mask; - uint32_t bds_used_mask; - uint32_t gps_count; - uint32_t glo_count; - uint32_t gal_count; - uint32_t qzss_count; - uint32_t bds_count; + 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_l5_count; + uint32_t glo_g1_count; + uint32_t glo_g2_count; + uint32_t gal_e1_count; + uint32_t gal_e5_count; + uint32_t qzss_l1_count; + uint32_t qzss_l5_count; + uint32_t bds_b1_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: + 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 @@ -92,6 +393,7 @@ SIDE EFFECTS 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)); @@ -103,56 +405,97 @@ static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_nmea_sv_meta& sv_meta, sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'P'; sv_meta.mask = sv_cache_info.gps_used_mask; - sv_meta.svCount = sv_cache_info.gps_count; - sv_meta.signalId = 1; sv_meta.systemId = SYSTEM_ID_GPS; + if (GNSS_SIGNAL_GPS_L1CA == signalType) { + sv_meta.svCount = sv_cache_info.gps_l1_count; + } else if (GNSS_SIGNAL_GPS_L5 == signalType) { + sv_meta.svCount = sv_cache_info.gps_l5_count; + } 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; - sv_meta.svCount = sv_cache_info.glo_count; // GLONASS SV ids are from 65-96 sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET; - sv_meta.signalId = 1; sv_meta.systemId = SYSTEM_ID_GLONASS; + if (GNSS_SIGNAL_GLONASS_G1 == signalType) { + sv_meta.svCount = sv_cache_info.glo_g1_count; + } else if (GNSS_SIGNAL_GLONASS_G2 == signalType) { + sv_meta.svCount = sv_cache_info.glo_g2_count; + } 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; - sv_meta.svCount = sv_cache_info.gal_count; - sv_meta.signalId = 7; sv_meta.systemId = SYSTEM_ID_GALILEO; + if (GNSS_SIGNAL_GALILEO_E1 == signalType) { + sv_meta.svCount = sv_cache_info.gal_e1_count; + } else if (GNSS_SIGNAL_GALILEO_E5A == signalType) { + sv_meta.svCount = sv_cache_info.gal_e5_count; + } break; case GNSS_SV_TYPE_QZSS: - sv_meta.talker[0] = 'P'; + sv_meta.talker[0] = 'G'; sv_meta.talker[1] = 'Q'; sv_meta.mask = sv_cache_info.qzss_used_mask; - sv_meta.svCount = sv_cache_info.qzss_count; - // QZSS SV ids are from 193-197. So keep svIdOffset 0 - sv_meta.signalId = 0; + // QZSS SV ids are from 193-199. So keep svIdOffset -192 + sv_meta.svIdOffset = QZSS_SV_ID_OFFSET; sv_meta.systemId = SYSTEM_ID_QZSS; + if (GNSS_SIGNAL_QZSS_L1CA == signalType) { + sv_meta.svCount = sv_cache_info.qzss_l1_count; + } else if (GNSS_SIGNAL_QZSS_L5 == signalType) { + sv_meta.svCount = sv_cache_info.qzss_l5_count; + } break; case GNSS_SV_TYPE_BEIDOU: - sv_meta.talker[0] = 'P'; - sv_meta.talker[1] = 'Q'; + sv_meta.talker[0] = 'G'; + sv_meta.talker[1] = 'B'; sv_meta.mask = sv_cache_info.bds_used_mask; - sv_meta.svCount = sv_cache_info.bds_count; // BDS SV ids are from 201-235. So keep svIdOffset 0 - sv_meta.signalId = 0; - sv_meta.systemId = SYSTEM_ID_BEIDOU; + sv_meta.systemId = SYSTEM_ID_BDS; + if (GNSS_SIGNAL_BEIDOU_B1I == signalType) { + sv_meta.svCount = sv_cache_info.bds_b1_count; + } else if (GNSS_SIGNAL_BEIDOU_B2AI == signalType) { + sv_meta.svCount = sv_cache_info.bds_b2_count; + } + 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 0 + sv_meta.systemId = SYSTEM_ID_NAVIC; + if (GNSS_SIGNAL_NAVIC_L5 == signalType) { + sv_meta.svCount = sv_cache_info.navic_l5_count; + } 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) > 1) + (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, @@ -240,27 +583,31 @@ static uint32_t loc_nmea_generate_GSA(const GpsLocationExtended &locationExtende int length = 0; uint32_t svUsedCount = 0; - uint32_t svUsedList[32] = {0}; + uint32_t svUsedList[64] = {0}; char fixType = '\0'; const char* talker = sv_meta_p->talker; uint32_t svIdOffset = sv_meta_p->svIdOffset; - uint32_t mask = sv_meta_p->mask; + uint64_t mask = sv_meta_p->mask; + + if(sv_meta_p->svType != GNSS_SV_TYPE_GLONASS) { + svIdOffset = 0; + } - for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) + for (uint8_t i = 1; mask > 0 && svUsedCount < 64; i++) { if (mask & 1) svUsedList[svUsedCount++] = i + svIdOffset; mask = mask >> 1; } - if (svUsedCount == 0 && GNSS_SV_TYPE_GPS != sv_meta_p->svType) + if (svUsedCount == 0) return 0; - if (svUsedCount == 0) + if (sv_meta_p->totalSvUsedCount == 0) fixType = '1'; // no fix - else if (svUsedCount <= 3) + else if (sv_meta_p->totalSvUsedCount <= 3) fixType = '2'; // 2D fix else fixType = '3'; // 3D fix @@ -371,13 +718,9 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, const char* talker = sv_meta_p->talker; uint32_t svIdOffset = sv_meta_p->svIdOffset; int svCount = sv_meta_p->svCount; - if (svCount <= 0) { - // no svs in view, so just send a blank $--GSV sentence - snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,%d", talker, sv_meta_p->signalId); - length = loc_nmea_put_checksum(sentence, bufSize); - nmeaArraystr.push_back(sentence); + LOC_LOGV("No SV in view for talker ID:%s, signal ID:%X", talker, sv_meta_p->signalId); return; } @@ -403,10 +746,49 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, for (int i=0; (svNumber <= svNotify.count) && (i < 4); svNumber++) { - if (sv_meta_p->svType == svNotify.gnssSvs[svNumber - 1].type) + 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->svType == svNotify.gnssSvs[svNumber - 1].type && + sv_meta_p->signalId == convert_signalType_to_signalId(signalType)) { + uint16_t svId = svNotify.gnssSvs[svNumber - 1].svId; + // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here + if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type) { + svId = svId - (QZSS_SV_PRN_MIN - 1); + } length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,", - svNotify.gnssSvs[svNumber - 1].svId + svIdOffset, + svId + svIdOffset, (int)(0.5 + svNotify.gnssSvs[svNumber - 1].elevation), //float to int (int)(0.5 + svNotify.gnssSvs[svNumber - 1].azimuth)); //float to int @@ -438,7 +820,7 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } // append signalId - length = snprintf(pMarker, lengthRemaining,",%d",sv_meta_p->signalId); + length = snprintf(pMarker, lengthRemaining,",%X",sv_meta_p->signalId); pMarker += length; lengthRemaining -= length; @@ -449,6 +831,330 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, } //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); +} + +/*=========================================================================== +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) { + + ggaGpsQuality[0] = '0'; // 0 means no fix + rmcModeIndicator = 'N'; // N means no fix + vtgModeIndicator = 'N'; // N means no fix + + do { + // GGA fix quality is defined in NMEA spec as below: + // https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_GGA.html + // Fix quality: 0 = invalid + // 1 = GPS fix (SPS) + // 2 = DGPS fix + // 3 = PPS fix + // 4 = Real Time Kinematic + // 5 = Float RTK + // 6 = estimated (dead reckoning) (2.3 feature) + // 7 = Manual input mode + // 8 = Simulation mode + 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 + 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 + 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 + 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 + 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 + 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 + 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) + 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 @@ -475,11 +1181,20 @@ SIDE EFFECTS ===========================================================================*/ 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 &nmeaArraystr) { ENTRY_LOG(); - time_t utcTime(location.gpsLocation.timestamp/1000); + + LocGpsUtcTime utcPosTimestamp = 0; + bool inLsTransition = false; + + inLsTransition = get_utctime_with_leapsecond_transition + (location, locationExtended, systemInfo, utcPosTimestamp); + + time_t utcTime(utcPosTimestamp/1000); tm * pTm = gmtime(&utcTime); if (NULL == pTm) { LOC_LOGE("gmtime failed"); @@ -487,6 +1202,10 @@ void loc_nmea_generate_pos(const UlpLocation &location, } 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; @@ -497,22 +1216,45 @@ void loc_nmea_generate_pos(const UlpLocation &location, int utcMinutes = pTm->tm_min; int utcSeconds = pTm->tm_sec; int utcMSeconds = (location.gpsLocation.timestamp)%1000; - loc_sv_cache_info sv_cache_info = {}; + 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 = - (uint32_t)locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask; sv_cache_info.glo_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask; sv_cache_info.gal_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask; - sv_cache_info.qzss_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask; + locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask; sv_cache_info.bds_used_mask = - (uint32_t)locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_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'}; + char modeIndicator[7] = {0}; uint32_t svUsedCount = 0; uint32_t count = 0; loc_nmea_sv_meta sv_meta; @@ -521,8 +1263,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, + GNSS_SIGNAL_GPS_L1CA, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -535,8 +1277,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, + GNSS_SIGNAL_GLONASS_G1, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -549,8 +1291,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, // ------------------- count = loc_nmea_generate_GSA(locationExtended, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, true), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, + GNSS_SIGNAL_GALILEO_E1, true), nmeaArraystr); if (count > 0) { svUsedCount += count; @@ -558,31 +1300,39 @@ void loc_nmea_generate_pos(const UlpLocation &location, talker[1] = sv_meta.talker[1]; } - // -------------------------- - // ---$PQGSA/$GNGSA (QZSS)--- - // -------------------------- - + // ---------------------------- + // ---$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_QZSS, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, + GNSS_SIGNAL_BEIDOU_B1I, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } - // ---------------------------- - // ---$PQGSA/$GNGSA (BEIDOU)--- - // ---------------------------- + // -------------------------- + // ---$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_BEIDOU, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, + GNSS_SIGNAL_QZSS_L1CA, true), nmeaArraystr); if (count > 0) { svUsedCount += count; - // talker should be default "GP". If GPS, GLO etc is used, it should be "GN" + talker[0] = sv_meta.talker[0]; + talker[1] = sv_meta.talker[1]; } + char ggaGpsQuality[3] = {'0', '\0', '\0'}; + char rmcModeIndicator = 'N'; + char vtgModeIndicator = 'N'; + loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality, + ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); + // ------------------- // ------$--VTG------- // ------------------- @@ -637,27 +1387,57 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - // N means no fix - length = snprintf(pMarker, lengthRemaining, "%c", 'N'); - else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - // D means differential - length = snprintf(pMarker, lengthRemaining, "%c", 'D'); - else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - // E means estimated (dead reckoning) - length = snprintf(pMarker, lengthRemaining, "%c", 'E'); - else // A means autonomous - length = snprintf(pMarker, lengthRemaining, "%c", 'A'); + length = snprintf(pMarker, lengthRemaining, "%c", vtgModeIndicator); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); 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; - lengthRemaining = sizeof(sentence); + pMarker = sentence_RMC; + lengthRemaining = sizeof(sentence_RMC); length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," , talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10); @@ -672,8 +1452,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) { - double latitude = location.gpsLocation.latitude; - double longitude = location.gpsLocation.longitude; + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; char latHemisphere; char lonHemisphere; double latMinutes; @@ -795,17 +1575,176 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - // N means no fix - length = snprintf(pMarker, lengthRemaining, "%c", 'N'); + length = snprintf(pMarker, lengthRemaining, "%c", rmcModeIndicator); + 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_RMC, sizeof(sentence_RMC)); + + // ------------------- + // ------$--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; + + if(!(sv_cache_info.gps_used_mask ? 1 : 0)) + modeIndicator[0] = 'N'; else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - // D means differential - length = snprintf(pMarker, lengthRemaining, "%c", 'D'); + modeIndicator[0] = 'D'; else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - // E means estimated (dead reckoning) - length = snprintf(pMarker, lengthRemaining, "%c", 'E'); - else // A means autonomous - length = snprintf(pMarker, lengthRemaining, "%c", 'A'); + modeIndicator[0] = 'E'; + else + modeIndicator[0] = 'A'; + if(!(sv_cache_info.glo_used_mask ? 1 : 0)) + modeIndicator[1] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[1] = 'E'; + else + modeIndicator[1] = 'A'; + if(!(sv_cache_info.gal_used_mask ? 1 : 0)) + modeIndicator[2] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[2] = 'E'; + else + modeIndicator[2] = 'A'; + if(!(sv_cache_info.bds_used_mask ? 1 : 0)) + modeIndicator[3] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[3] = 'E'; + else + modeIndicator[3] = 'A'; + if(!(sv_cache_info.qzss_used_mask ? 1 : 0)) + modeIndicator[4] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[4] = 'E'; + else + modeIndicator[4] = 'A'; + if(!(sv_cache_info.navic_used_mask ? 1 : 0)) + modeIndicator[5] = 'N'; + else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) + modeIndicator[5] = 'E'; + else + modeIndicator[5] = 'A'; + modeIndicator[6] = '\0'; + for(int index = 5; index > 0 && 'N' == modeIndicator[index]; index--) { + modeIndicator[index] = '\0'; + } + length = snprintf(pMarker, lengthRemaining,"%s,", modeIndicator); + + 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,",,"); + } pMarker += length; lengthRemaining -= length; @@ -815,15 +1754,15 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); - nmeaArraystr.push_back(sentence); + length = loc_nmea_put_checksum(sentence_GNS, sizeof(sentence_GNS)); + // ------------------- // ------$--GGA------- // ------------------- - pMarker = sentence; - lengthRemaining = sizeof(sentence); + pMarker = sentence_GGA; + lengthRemaining = sizeof(sentence_GGA); length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," , talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); @@ -838,8 +1777,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, if (location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) { - double latitude = location.gpsLocation.latitude; - double longitude = location.gpsLocation.longitude; + double latitude = ref_lla.lat; + double longitude = ref_lla.lon; char latHemisphere; char lonHemisphere; double latMinutes; @@ -885,28 +1824,18 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker += length; lengthRemaining -= length; - char gpsQuality; - if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) - gpsQuality = '0'; // 0 means no fix - else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask) - gpsQuality = '2'; // 2 means DGPS fix - else if (LOC_POS_TECH_MASK_SENSORS == locationExtended.tech_mask) - gpsQuality = '6'; // 6 means estimated (dead reckoning) - else - gpsQuality = '1'; // 1 means GPS fix - // 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, "%c,%02d,%.1f,", - gpsQuality, svUsedCount, locationExtended.hdop); + length = snprintf(pMarker, lengthRemaining, "%s,%02d,%.1f,", + ggaGpsQuality, svUsedCount, locationExtended.hdop); } else { // no hdop - length = snprintf(pMarker, lengthRemaining, "%c,%02d,,", - gpsQuality, svUsedCount); + length = snprintf(pMarker, lengthRemaining, "%s,%02d,,", + ggaGpsQuality, svUsedCount); } if (length < 0 || length >= lengthRemaining) @@ -939,35 +1868,52 @@ void loc_nmea_generate_pos(const UlpLocation &location, (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) { length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,", - location.gpsLocation.altitude - locationExtended.altitudeMeanSeaLevel); + ref_lla.alt - locationExtended.altitudeMeanSeaLevel); } else { length = snprintf(pMarker, lengthRemaining,",,,"); } - length = loc_nmea_put_checksum(sentence, sizeof(sentence)); - nmeaArraystr.push_back(sentence); + length = loc_nmea_put_checksum(sentence_GGA, sizeof(sentence_GGA)); + + // ------$--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); + } //Send blank NMEA reports for non-final fixes else { - strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$PQGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + strlcpy(sentence, "$GPDTM,,,,,,,,", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); + strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); - strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N,V", sizeof(sentence)); + strlcpy(sentence, "$GPGNS,,,,,,N,,,,,,,V", sizeof(sentence)); length = loc_nmea_put_checksum(sentence, sizeof(sentence)); nmeaArraystr.push_back(sentence); @@ -1017,9 +1963,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.gps_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.gps_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if (GNSS_SIGNAL_GPS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) { + sv_cache_info.gps_l5_count++; + } else { + // GNSS_SIGNAL_GPS_L1CA or default + // If no signal type in report, it means default L1 + sv_cache_info.gps_l1_count++; } - sv_cache_info.gps_count++; } else if (GNSS_SV_TYPE_GLONASS == svNotify.gnssSvs[svNumber - 1].type) { @@ -1029,9 +1981,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.glo_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.glo_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if (GNSS_SIGNAL_GLONASS_G2 == svNotify.gnssSvs[svNumber - 1].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++; } - sv_cache_info.glo_count++; } else if (GNSS_SV_TYPE_GALILEO == svNotify.gnssSvs[svNumber - 1].type) { @@ -1041,9 +1999,15 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.gal_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.gal_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if(GNSS_SIGNAL_GALILEO_E5A == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){ + sv_cache_info.gal_e5_count++; + } else { + // GNSS_SIGNAL_GALILEO_E1 or default + // If no signal type in report, it means default E1 + sv_cache_info.gal_e1_count++; } - sv_cache_info.gal_count++; } else if (GNSS_SV_TYPE_QZSS == svNotify.gnssSvs[svNumber - 1].type) { @@ -1053,9 +2017,17 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.qzss_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + // For QZSS we adjusted SV id's in GnssAdapter, we need to re-adjust here + sv_cache_info.qzss_used_mask |= + (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - (QZSS_SV_PRN_MIN - 1) - 1)); + } + if (GNSS_SIGNAL_QZSS_L5 == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) { + sv_cache_info.qzss_l5_count++; + } else { + // GNSS_SIGNAL_QZSS_L1CA or default + // If no signal type in report, it means default L1 + sv_cache_info.qzss_l1_count++; } - sv_cache_info.qzss_count++; } else if (GNSS_SV_TYPE_BEIDOU == svNotify.gnssSvs[svNumber - 1].type) { @@ -1065,50 +2037,117 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.bds_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.bds_used_mask |= (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + } + if(GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask){ + sv_cache_info.bds_b2_count++; + } else { + // GNSS_SIGNAL_BEIDOU_B1I or default + // If no signal type in report, it means default B1I + sv_cache_info.bds_b1_count++; + } + } + else if (GNSS_SV_TYPE_NAVIC == svNotify.gnssSvs[svNumber - 1].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[svNumber - 1].gnssSvOptionsMask & + GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) + { + sv_cache_info.navic_used_mask |= + (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); } - sv_cache_info.bds_count++; + // GNSS_SIGNAL_NAVIC_L5 is the only signal type for NAVIC + sv_cache_info.navic_l5_count++; } } loc_nmea_sv_meta sv_meta; - // ------------------ - // ------$GPGSV------ - // ------------------ + // --------------------- + // ------$GPGSV:L1CA---- + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, false), nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GPS, + GNSS_SIGNAL_GPS_L1CA, false), nmeaArraystr); + + // --------------------- + // ------$GPGSV:L5------ + // --------------------- - // ------------------ - // ------$GLGSV------ - // ------------------ + 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); + // --------------------- + // ------$GLGSV:G1------ + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, false), - nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GLONASS, + GNSS_SIGNAL_GLONASS_G1, false), nmeaArraystr); - // ------------------ - // ------$GAGSV------ - // ------------------ + // --------------------- + // ------$GLGSV:G2------ + // --------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_GALILEO, false), - nmeaArraystr); + 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); // ------------------------- - // ------$PQGSV (QZSS)------ + // ------$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); + + // ----------------------------- + // ------$PQGSV (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); + + // ----------------------------- + // ------$PQGSV (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); + // ----------------------------- + // ------$PQGSV (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); + + // ----------------------------- + // ------$PQGSV (BEIDOU:B2AI)--- + // ----------------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_QZSS, false), nmeaArraystr); + loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, + GNSS_SIGNAL_BEIDOU_B2AI,false), nmeaArraystr); - // --------------------------- - // ------$PQGSV (BEIDOU)------ - // --------------------------- + // ----------------------------- + // ------$GIGSV (NAVIC:L5)------ + // ----------------------------- loc_nmea_generate_GSV(svNotify, sentence, sizeof(sentence), - loc_nmea_sv_meta_init(sv_meta, sv_cache_info, GNSS_SV_TYPE_BEIDOU, false), - nmeaArraystr); + 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 index 585a9c1..a9cafb7 100644 --- a/gps/utils/loc_nmea.h +++ b/gps/utils/loc_nmea.h @@ -35,12 +35,51 @@ #include #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 &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 &nmeaArraystr); #define DEBUG_NMEA_MINSIZE 6 diff --git a/gps/utils/loc_target.cpp b/gps/utils/loc_target.cpp index 569f3a7..3ee42e6 100644 --- a/gps/utils/loc_target.cpp +++ b/gps/utils/loc_target.cpp @@ -54,6 +54,7 @@ #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" @@ -79,6 +80,11 @@ static int read_a_line(const char * file_path, char * line, int line_size) 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); @@ -129,16 +135,53 @@ void loc_get_auto_platform_name(char *platform_name, int array_length) } } +/*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 id[] = "/sys/devices/soc0/soc_id"; static const char hw_platform_dep[] = "/sys/devices/system/soc/soc0/hw_platform"; - static const char id_dep[] = "/sys/devices/system/soc/soc0/id"; static const char mdm[] = "/target"; // mdm target we are using char rd_hw_platform[LINE_LEN]; @@ -154,11 +197,8 @@ unsigned int loc_get_target(void) } else { read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN); } - if (!access(id, F_OK)) { - read_a_line(id, rd_id, LINE_LEN); - } else { - read_a_line(id_dep, rd_id, 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)); @@ -175,7 +215,8 @@ unsigned int loc_get_target(void) } if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) || - !memcmp(baseband, STR_SDC, LENGTH(STR_SDC)) ) { + !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)]) ) diff --git a/gps/utils/loc_target.h b/gps/utils/loc_target.h index 172b475..2dcd895 100644 --- a/gps/utils/loc_target.h +++ b/gps/utils/loc_target.h @@ -54,6 +54,10 @@ 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. */ diff --git a/gps/utils/log_util.h b/gps/utils/log_util.h index feb4d3c..192baeb 100644 --- a/gps/utils/log_util.h +++ b/gps/utils/log_util.h @@ -39,13 +39,41 @@ #include #include #include +#include #include -#include #ifndef LOG_TAG #define LOG_TAG "GPS_UTILS" #endif /* LOG_TAG */ +// LE targets with no logcat support +#ifdef FEATURE_EXTERNAL_AP +#include +#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 @@ -148,6 +176,7 @@ extern char* get_timestamp(char* str, unsigned long buf_size); #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) @@ -165,6 +194,8 @@ extern char* get_timestamp(char* str, unsigned long buf_size); #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) diff --git a/gps/utils/msg_q.c b/gps/utils/msg_q.c index 76c1478..2d49b4a 100644 --- a/gps/utils/msg_q.c +++ b/gps/utils/msg_q.c @@ -265,6 +265,51 @@ msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj) 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 diff --git a/gps/utils/msg_q.h b/gps/utils/msg_q.h index 453b8ce..16df494 100644 --- a/gps/utils/msg_q.h +++ b/gps/utils/msg_q.h @@ -157,6 +157,29 @@ SIDE EFFECTS ===========================================================================*/ 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 diff --git a/manifest.xml b/manifest.xml index a06eb00..a31bf79 100644 --- a/manifest.xml +++ b/manifest.xml @@ -373,15 +373,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. widevine - - android.hardware.gnss - hwbinder - 1.1 - - IGnss - default - - vendor.display.config hwbinder @@ -391,15 +382,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - - vendor.qti.gnss - hwbinder - 1.0 - - ILocHidlGnss - gnss_vendor - - vendor.qti.data.factory hwbinder diff --git a/msm8996.mk b/msm8996.mk index 796c156..532b55c 100755 --- a/msm8996.mk +++ b/msm8996.mk @@ -138,6 +138,7 @@ PRODUCT_COPY_FILES += \ # Bluetooth PRODUCT_PACKAGES += \ android.hardware.bluetooth@1.0.vendor \ + android.hardware.bluetooth@1.0 \ android.hardware.bluetooth.audio-impl \ audio.bluetooth.default @@ -215,13 +216,14 @@ PRODUCT_PACKAGES += \ # GPS / Location PRODUCT_PACKAGES += \ - android.hardware.gnss@1.0-impl-qti \ - android.hardware.gnss@1.0-service-qti \ + android.hardware.gnss@2.0-impl-qti \ + android.hardware.gnss@2.0-service-qti \ android.hardware.gnss@1.1.vendor \ libcurl \ libgnss \ libgnsspps \ - libsensorndkbridge + libsensorndkbridge \ + libwifi-hal-ctrl PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/configs/gps//flp.conf:$(TARGET_COPY_OUT_VENDOR)/etc/flp.conf \ @@ -396,10 +398,6 @@ PRODUCT_PACKAGES += \ # PRODUCT_VENDOR_VERITY_PARTITION=/dev/block/bootdevice/by-name/factory # $(call inherit-product, build/target/product/verity.mk) -# Vibrator -PRODUCT_PACKAGES += \ - vendor.qti.hardware.vibrator.service - PRODUCT_COPY_FILES += \ prebuilts/vndk/v29/arm64/arch-arm64-armv8-a/shared/vndk-sp/libcutils.so:$(TARGET_COPY_OUT_SYSTEM_EXT)/lib64/libcutils-v29.so \ prebuilts/vndk/v32/arm64/arch-arm64-armv8-a/shared/vndk-sp/libhidlbase.so:$(TARGET_COPY_OUT_SYSTEM)/lib64/libhidlbase-v32.so \ @@ -409,7 +407,7 @@ PRODUCT_COPY_FILES += \ # WiFi PRODUCT_PACKAGES += \ - android.hardware.wifi-service \ + android.hardware.wifi@1.0-service.legacy \ libwpa_client \ hostapd \ WifiOverlay \ diff --git a/wifi/wifi_legacy_service/1.0-legacy/Android.bp b/wifi/wifi_legacy_service/1.0-legacy/Android.bp new file mode 100644 index 0000000..0d0dfdf --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/Android.bp @@ -0,0 +1,182 @@ +// Copyright (C) 2021 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. + +soong_config_module_type { + name: "wifi_hal_cc_defaults", + module_type: "cc_defaults", + config_namespace: "wifi", + bool_variables: [ + "hidl_feature_aware", // WIFI_HIDL_FEATURE_AWARE + "hidl_feature_dual_interface", // WIFI_HIDL_FEATURE_DUAL_INTERFACE + "hidl_feature_disable_ap", // WIFI_HIDL_FEATURE_DISABLE_AP + "hidl_feature_disable_ap_mac_randomization", // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION + "avoid_iface_reset_mac_change", // WIFI_AVOID_IFACE_RESET_MAC_CHANGE + "wifi_skip_state_toggle_off_on_for_nan", // WIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN + ], + value_variables: [ + "hal_interface_combinations", // WIFI_HAL_INTERFACE_COMBINATIONS + ], + properties: [ + "cppflags", + ], +} + +wifi_hal_cc_defaults { + name: "android.hardware.wifi@1.0-service.legacy-cppflags-defaults", + soong_config_variables: { + hidl_feature_aware: { + cppflags: ["-DWIFI_HIDL_FEATURE_AWARE"], + }, + hidl_feature_dual_interface: { + cppflags: ["-DWIFI_HIDL_FEATURE_DUAL_INTERFACE"], + }, + hidl_feature_disable_ap: { + cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP"], + }, + hidl_feature_disable_ap_mac_randomization: { + cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION"], + }, + avoid_iface_reset_mac_change: { + cppflags: ["-DWIFI_AVOID_IFACE_RESET_MAC_CHANGE"], + }, + wifi_skip_state_toggle_off_on_for_nan: { + cppflags: ["-DWIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN"], + }, + hal_interface_combinations: { + cppflags: ["-DWIFI_HAL_INTERFACE_COMBINATIONS=%s"], + }, + }, +} + +cc_library_static { + name: "android.hardware.wifi@1.0-service.legacy-lib", + defaults: ["android.hardware.wifi@1.0-service.legacy-cppflags-defaults"], + proprietary: true, + compile_multilib: "first", + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + // Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed. + cflags: ["-Wno-error=implicit-fallthrough"], + srcs: [ + "hidl_struct_util.cpp", + "hidl_sync_util.cpp", + "ringbuffer.cpp", + "wifi.cpp", + "wifi_ap_iface.cpp", + "wifi_chip.cpp", + "wifi_feature_flags.cpp", + "wifi_iface_util.cpp", + "wifi_legacy_hal.cpp", + "wifi_legacy_hal_factory.cpp", + "wifi_legacy_hal_stubs.cpp", + "wifi_mode_controller.cpp", + "wifi_nan_iface.cpp", + "wifi_p2p_iface.cpp", + "wifi_rtt_controller.cpp", + "wifi_sta_iface.cpp", + "wifi_status_util.cpp", + ], + + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + + export_include_dirs: ["."], +} + +cc_binary { + name: "android.hardware.wifi@1.0-service.legacy", + vintf_fragments: ["android.hardware.wifi@1.0-service.legacy.xml"], + relative_install_path: "hw", + proprietary: true, + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + srcs: ["service.cpp"], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + static_libs: ["android.hardware.wifi@1.0-service.legacy-lib"], + init_rc: ["android.hardware.wifi@1.0-service.legacy.rc"], +} + +cc_binary { + name: "android.hardware.wifi@1.0-service.legacy-lazy", + vintf_fragments: ["android.hardware.wifi@1.0-service.legacy.xml"], + overrides: ["android.hardware.wifi@1.0-service.legacy"], + cflags: ["-DLAZY_SERVICE"], + relative_install_path: "hw", + proprietary: true, + cppflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + srcs: ["service.cpp"], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "liblog", + "libnl", + "libutils", + "libwifi-hal", + "libwifi-system-iface", + "libxml2", + "android.hardware.wifi@1.0", + "android.hardware.wifi@1.1", + "android.hardware.wifi@1.2", + "android.hardware.wifi@1.3", + "android.hardware.wifi@1.4", + "android.hardware.wifi@1.5", + "android.hardware.wifi@1.6", + ], + static_libs: ["android.hardware.wifi@1.0-service.legacy-lib"], + init_rc: ["android.hardware.wifi@1.0-service.legacy-lazy.rc"], +} diff --git a/wifi/wifi_legacy_service/1.0-legacy/THREADING.README b/wifi/wifi_legacy_service/1.0-legacy/THREADING.README new file mode 100644 index 0000000..8366ca0 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/THREADING.README @@ -0,0 +1,35 @@ +Vendor HAL Threading Model +========================== +The vendor HAL service has two threads: +1. HIDL thread: This is the main thread which processes all the incoming HIDL +RPC's. +2. Legacy HAL event loop thread: This is the thread forked off for processing +the legacy HAL event loop (wifi_event_loop()). This thread is used to process +any asynchronous netlink events posted by the driver. Any asynchronous +callbacks passed to the legacy HAL API's are invoked on this thread. + +Synchronization Concerns +======================== +wifi_legacy_hal.cpp has a bunch of global "C" style functions to handle the +legacy callbacks. Each of these "C" style function invokes a corresponding +"std::function" version of the callback which does the actual processing. +The variables holding these "std::function" callbacks are reset from the HIDL +thread when they are no longer used. For example: stopGscan() will reset the +corresponding "on_gscan_*" callback variables which were set when startGscan() +was invoked. This is not thread safe since these callback variables are +accesed from the legacy hal event loop thread as well. + +Synchronization Solution +======================== +Adding a global lock seems to be the most trivial solution to the problem. +a) All of the asynchronous "C" style callbacks will acquire the global lock +before invoking the corresponding "std::function" callback variables. +b) All of the HIDL methods will also acquire the global lock before processing +(in hidl_return_util::validateAndCall()). + +Note: It's important that we only acquire the global lock for asynchronous +callbacks, because there is no guarantee (or documentation to clarify) that the +synchronous callbacks are invoked on the same invocation thread. If that is not +the case in some implementation, we will end up deadlocking the system since the +HIDL thread would have acquired the global lock which is needed by the +synchronous callback executed on the legacy hal event loop thread. diff --git a/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc new file mode 100644 index 0000000..5bf3223 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy-lazy.rc @@ -0,0 +1,14 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service.legacy-lazy + interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default + interface android.hardware.wifi@1.6::IWifi default + oneshot + disabled + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc new file mode 100644 index 0000000..fb18f68 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.rc @@ -0,0 +1,12 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service.legacy + interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default + interface android.hardware.wifi@1.5::IWifi default + interface android.hardware.wifi@1.6::IWifi default + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml new file mode 100644 index 0000000..771fbaa --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/android.hardware.wifi@1.0-service.legacy.xml @@ -0,0 +1,11 @@ + + + android.hardware.wifi + hwbinder + 1.6 + + IWifi + default + + + diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h new file mode 100644 index 0000000..eb61472 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareBase.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef ANDROID_AUDIO_HARDWARE_BASE_H +#define ANDROID_AUDIO_HARDWARE_BASE_H + +#include + +#include + +namespace android_audio_legacy { + +// ---------------------------------------------------------------------------- + +/** + * AudioHardwareBase is a convenient base class used for implementing the + * AudioHardwareInterface interface. + */ +class AudioHardwareBase : public AudioHardwareInterface { + public: + AudioHardwareBase(); + virtual ~AudioHardwareBase() {} + + /** + * setMode is called when the audio mode changes. NORMAL mode is for + * standard audio playback, RINGTONE when a ringtone is playing, IN_CALL + * when a telephony call is in progress, IN_COMMUNICATION when a VoIP call is in progress. + */ + virtual status_t setMode(int mode); + + virtual status_t setParameters(const String8& keyValuePairs); + virtual String8 getParameters(const String8& keys); + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); + virtual status_t getMasterVolume(float* volume); + + /**This method dumps the state of the audio hardware */ + virtual status_t dumpState(int fd, const Vector& args); + + protected: + /** returns true if the given mode maps to a telephony or VoIP call is in progress */ + virtual bool isModeInCall(int mode) { + return ((mode == AudioSystem::MODE_IN_CALL) || + (mode == AudioSystem::MODE_IN_COMMUNICATION)); + }; + /** returns true if a telephony or VoIP call is in progress */ + virtual bool isInCall() { return isModeInCall(mMode); }; + int mMode; +}; + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIO_HARDWARE_BASE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h new file mode 100644 index 0000000..7befb79 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioHardwareInterface.h @@ -0,0 +1,296 @@ +/* + * 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. + */ + +#ifndef ANDROID_AUDIO_HARDWARE_INTERFACE_H +#define ANDROID_AUDIO_HARDWARE_INTERFACE_H + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +namespace android_audio_legacy { +using android::String16; +using android::String8; +using android::Vector; + +// ---------------------------------------------------------------------------- + +/** + * AudioStreamOut is the abstraction interface for the audio output hardware. + * + * It provides information about various properties of the audio output hardware driver. + */ +class AudioStreamOut { + public: + virtual ~AudioStreamOut() = 0; + + /** return audio sampling rate in hz - eg. 44100 */ + virtual uint32_t sampleRate() const = 0; + + /** returns size of output buffer - eg. 4800 */ + virtual size_t bufferSize() const = 0; + + /** + * returns the output channel mask + */ + virtual uint32_t channels() const = 0; + + /** + * return audio format in 8bit or 16bit PCM format - + * eg. AudioSystem:PCM_16_BIT + */ + virtual int format() const = 0; + + /** + * return the frame size (number of bytes per sample). + */ + uint32_t frameSize() const { + return audio_channel_count_from_out_mask(channels()) * + ((format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(int8_t)); + } + + /** + * return the audio hardware driver latency in milli seconds. + */ + virtual uint32_t latency() const = 0; + + /** + * Use this method in situations where audio mixing is done in the + * hardware. This method serves as a direct interface with hardware, + * allowing you to directly set the volume as apposed to via the framework. + * This method might produce multiple PCM outputs or hardware accelerated + * codecs, such as MP3 or AAC. + */ + virtual status_t setVolume(float left, float right) = 0; + + /** write audio buffer to driver. Returns number of bytes written */ + virtual ssize_t write(const void* buffer, size_t bytes) = 0; + + /** + * Put the audio hardware output into standby mode. Returns + * status based on include/utils/Errors.h + */ + virtual status_t standby() = 0; + + /** dump the state of the audio output device */ + virtual status_t dump(int fd, const Vector& args) = 0; + + // set/get audio output parameters. The function accepts a list of parameters + // key value pairs in the form: key1=value1;key2=value2;... + // Some keys are reserved for standard parameters (See AudioParameter class). + // If the implementation does not accept a parameter change while the output is + // active but the parameter is acceptable otherwise, it must return INVALID_OPERATION. + // The audio flinger will put the output in standby and then change the parameter value. + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // return the number of audio frames written by the audio dsp to DAC since + // the output has exited standby + virtual status_t getRenderPosition(uint32_t* dspFrames) = 0; + + /** + * get the local time at which the next write to the audio driver will be + * presented + */ + virtual status_t getNextWriteTimestamp(int64_t* timestamp); + + /** + * Return a recent count of the number of audio frames presented to an external observer. + */ + virtual status_t getPresentationPosition(uint64_t* frames, struct timespec* timestamp); +}; + +/** + * AudioStreamIn is the abstraction interface for the audio input hardware. + * + * It defines the various properties of the audio hardware input driver. + */ +class AudioStreamIn { + public: + virtual ~AudioStreamIn() = 0; + + /** return audio sampling rate in hz - eg. 44100 */ + virtual uint32_t sampleRate() const = 0; + + /** return the input buffer size allowed by audio driver */ + virtual size_t bufferSize() const = 0; + + /** return input channel mask */ + virtual uint32_t channels() const = 0; + + /** + * return audio format in 8bit or 16bit PCM format - + * eg. AudioSystem:PCM_16_BIT + */ + virtual int format() const = 0; + + /** + * return the frame size (number of bytes per sample). + */ + uint32_t frameSize() const { + return audio_channel_count_from_in_mask(channels()) * + ((format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(int8_t)); + } + + /** set the input gain for the audio driver. This method is for + * for future use */ + virtual status_t setGain(float gain) = 0; + + /** read audio buffer in from audio driver */ + virtual ssize_t read(void* buffer, ssize_t bytes) = 0; + + /** dump the state of the audio input device */ + virtual status_t dump(int fd, const Vector& args) = 0; + + /** + * Put the audio hardware input into standby mode. Returns + * status based on include/utils/Errors.h + */ + virtual status_t standby() = 0; + + // set/get audio input parameters. The function accepts a list of parameters + // key value pairs in the form: key1=value1;key2=value2;... + // Some keys are reserved for standard parameters (See AudioParameter class). + // If the implementation does not accept a parameter change while the output is + // active but the parameter is acceptable otherwise, it must return INVALID_OPERATION. + // The audio flinger will put the input in standby and then change the parameter value. + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // Return the number of input frames lost in the audio driver since the last call of this + // function. Audio driver is expected to reset the value to 0 and restart counting upon + // returning the current value by this function call. Such loss typically occurs when the user + // space process is blocked longer than the capacity of audio driver buffers. Unit: the number + // of input audio frames + virtual unsigned int getInputFramesLost() const = 0; + + virtual status_t addAudioEffect(effect_handle_t effect) = 0; + virtual status_t removeAudioEffect(effect_handle_t effect) = 0; +}; + +/** + * AudioHardwareInterface.h defines the interface to the audio hardware abstraction layer. + * + * The interface supports setting and getting parameters, selecting audio routing + * paths, and defining input and output streams. + * + * AudioFlinger initializes the audio hardware and immediately opens an output stream. + * You can set Audio routing to output to handset, speaker, Bluetooth, or a headset. + * + * The audio input stream is initialized when AudioFlinger is called to carry out + * a record operation. + */ +class AudioHardwareInterface { + public: + virtual ~AudioHardwareInterface() {} + + /** + * check to see if the audio hardware interface has been initialized. + * return status based on values defined in include/utils/Errors.h + */ + virtual status_t initCheck() = 0; + + /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */ + virtual status_t setVoiceVolume(float volume) = 0; + + /** + * set the audio volume for all audio activities other than voice call. + * Range between 0.0 and 1.0. If any value other than NO_ERROR is returned, + * the software mixer will emulate this capability. + */ + virtual status_t setMasterVolume(float volume) = 0; + + /** + * Get the current master volume value for the HAL, if the HAL supports + * master volume control. AudioFlinger will query this value from the + * primary audio HAL when the service starts and use the value for setting + * the initial master volume across all HALs. + */ + virtual status_t getMasterVolume(float* volume) = 0; + + /** + * setMode is called when the audio mode changes. NORMAL mode is for + * standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL + * when a call is in progress. + */ + virtual status_t setMode(int mode) = 0; + + // mic mute + virtual status_t setMicMute(bool state) = 0; + virtual status_t getMicMute(bool* state) = 0; + + // set/get global audio parameters + virtual status_t setParameters(const String8& keyValuePairs) = 0; + virtual String8 getParameters(const String8& keys) = 0; + + // Returns audio input buffer size according to parameters passed or 0 if one of the + // parameters is not supported + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0; + + /** This method creates and opens the audio hardware output stream */ + virtual AudioStreamOut* openOutputStream(uint32_t devices, int* format = 0, + uint32_t* channels = 0, uint32_t* sampleRate = 0, + status_t* status = 0) = 0; + virtual AudioStreamOut* openOutputStreamWithFlags( + uint32_t devices, audio_output_flags_t flags = (audio_output_flags_t)0, int* format = 0, + uint32_t* channels = 0, uint32_t* sampleRate = 0, status_t* status = 0) = 0; + virtual void closeOutputStream(AudioStreamOut* out) = 0; + + /** This method creates and opens the audio hardware input stream */ + virtual AudioStreamIn* openInputStream(uint32_t devices, int* format, uint32_t* channels, + uint32_t* sampleRate, status_t* status, + AudioSystem::audio_in_acoustics acoustics) = 0; + virtual void closeInputStream(AudioStreamIn* in) = 0; + + /**This method dumps the state of the audio hardware */ + virtual status_t dumpState(int fd, const Vector& args) = 0; + + virtual status_t setMasterMute(bool muted) = 0; + + static AudioHardwareInterface* create(); + + virtual int createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources, + unsigned int num_sinks, const struct audio_port_config* sinks, + audio_patch_handle_t* handle) = 0; + + virtual int releaseAudioPatch(audio_patch_handle_t handle) = 0; + + virtual int getAudioPort(struct audio_port* port) = 0; + + virtual int setAudioPortConfig(const struct audio_port_config* config) = 0; + + protected: + virtual status_t dump(int fd, const Vector& args) = 0; +}; + +// ---------------------------------------------------------------------------- + +extern "C" AudioHardwareInterface* createAudioHardware(void); + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIO_HARDWARE_INTERFACE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h new file mode 100644 index 0000000..ec9c432 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyInterface.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2009 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_AUDIOPOLICYINTERFACE_H +#define ANDROID_AUDIOPOLICYINTERFACE_H + +#include +#include +#include + +#include +#include + +namespace android_audio_legacy { +using android::String8; +using android::ToneGenerator; +using android::Vector; + +// ---------------------------------------------------------------------------- + +// The AudioPolicyInterface and AudioPolicyClientInterface classes define the communication +// interfaces between the platform specific audio policy manager and Android generic audio policy +// manager. The platform specific audio policy manager must implement methods of the +// AudioPolicyInterface class. This implementation makes use of the AudioPolicyClientInterface to +// control the activity and configuration of audio input and output streams. +// +// The platform specific audio policy manager is in charge of the audio routing and volume control +// policies for a given platform. +// The main roles of this module are: +// - keep track of current system state (removable device connections, phone state, user +// requests...). System state changes and user actions are notified to audio policy manager with +// methods of the AudioPolicyInterface. +// - process getOutput() queries received when AudioTrack objects are created: Those queries +// return a handler on an output that has been selected, configured and opened by the audio policy +// manager and that must be used by the AudioTrack when registering to the AudioFlinger with the +// createTrack() method. When the AudioTrack object is released, a putOutput() query is received +// and the audio policy manager can decide to close or reconfigure the output depending on other +// streams using this output and current system state. +// - similarly process getInput() and putInput() queries received from AudioRecord objects and +// configure audio inputs. +// - process volume control requests: the stream volume is converted from an index value (received +// from UI) to a float value applicable to each output as a function of platform specific settings +// and current output route (destination device). It also make sure that streams are not muted if +// not allowed (e.g. camera shutter sound in some countries). +// +// The platform specific audio policy manager is provided as a shared library by platform vendors +// (as for libaudio.so) and is linked with libaudioflinger.so + +// Audio Policy Manager Interface +class AudioPolicyInterface { + public: + virtual ~AudioPolicyInterface() {} + // + // configuration functions + // + + // indicate a change in device connection status + virtual status_t setDeviceConnectionState(audio_devices_t device, + AudioSystem::device_connection_state state, + const char* device_address) = 0; + // retrieve a device connection status + virtual AudioSystem::device_connection_state getDeviceConnectionState( + audio_devices_t device, const char* device_address) = 0; + // indicate a change in phone state. Valid phones states are defined by AudioSystem::audio_mode + virtual void setPhoneState(int state) = 0; + // force using a specific device category for the specified usage + virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) = 0; + // retrieve current device category forced for a given usage + virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage) = 0; + // set a system property (e.g. camera sound always audible) + virtual void setSystemProperty(const char* property, const char* value) = 0; + // check proper initialization + virtual status_t initCheck() = 0; + + // + // Audio routing query functions + // + + // request an output appropriate for playback of the supplied stream type and parameters + virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::output_flags flags, + const audio_offload_info_t* offloadInfo) = 0; + // indicates to the audio policy manager that the output starts being used by corresponding + // stream. + virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE) = 0; + // indicates to the audio policy manager that the output stops being used by corresponding + // stream. + virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE) = 0; + // releases the output. + virtual void releaseOutput(audio_io_handle_t output) = 0; + + // request an input appropriate for record from the supplied device with supplied parameters. + virtual audio_io_handle_t getInput(int inputSource, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::audio_in_acoustics acoustics) = 0; + // indicates to the audio policy manager that the input starts being used. + virtual status_t startInput(audio_io_handle_t input) = 0; + // indicates to the audio policy manager that the input stops being used. + virtual status_t stopInput(audio_io_handle_t input) = 0; + // releases the input. + virtual void releaseInput(audio_io_handle_t input) = 0; + + // + // volume control functions + // + + // initialises stream volume conversion parameters by specifying volume index range. + virtual void initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax) = 0; + + // sets the new stream volume at a level corresponding to the supplied index for the + // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // setting volume for all devices + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index, + audio_devices_t device) = 0; + + // retrieve current volume index for the specified stream and the + // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means + // querying the volume of the active device. + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int* index, + audio_devices_t device) = 0; + + // return the strategy corresponding to a given stream type + virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0; + + // return the enabled output devices for the given stream type + virtual audio_devices_t getDevicesForStream(AudioSystem::stream_type stream) = 0; + + // Audio effect management + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t* desc) = 0; + virtual status_t registerEffect(const effect_descriptor_t* desc, audio_io_handle_t io, + uint32_t strategy, audio_session_t session, int id) = 0; + virtual status_t unregisterEffect(int id) = 0; + virtual status_t setEffectEnabled(int id, bool enabled) = 0; + + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0; + virtual bool isStreamActiveRemotely(int stream, uint32_t inPastMs = 0) const = 0; + virtual bool isSourceActive(audio_source_t source) const = 0; + + // dump state + virtual status_t dump(int fd) = 0; + + virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0; +}; + +// Audio Policy client Interface +class AudioPolicyClientInterface { + public: + virtual ~AudioPolicyClientInterface() {} + + // + // Audio HW module functions + // + + // loads a HW module. + virtual audio_module_handle_t loadHwModule(const char* name) = 0; + + // + // Audio output Control functions + // + + // opens an audio output with the requested parameters. The parameter values can indicate to use + // the default values in case the audio policy manager has no specific requirements for the + // output being opened. When the function returns, the parameter values reflect the actual + // values used by the audio hardware output stream. The audio policy manager can check if the + // proposed parameters are suitable or not and act accordingly. + virtual audio_io_handle_t openOutput(audio_module_handle_t module, audio_devices_t* pDevices, + uint32_t* pSamplingRate, audio_format_t* pFormat, + audio_channel_mask_t* pChannelMask, uint32_t* pLatencyMs, + audio_output_flags_t flags, + const audio_offload_info_t* offloadInfo = NULL) = 0; + // creates a special output that is duplicated to the two outputs passed as arguments. The + // duplication is performed by a special mixer thread in the AudioFlinger. + virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, + audio_io_handle_t output2) = 0; + // closes the output stream + virtual status_t closeOutput(audio_io_handle_t output) = 0; + // suspends the output. When an output is suspended, the corresponding audio hardware output + // stream is placed in standby and the AudioTracks attached to the mixer thread are still + // processed but the output mix is discarded. + virtual status_t suspendOutput(audio_io_handle_t output) = 0; + // restores a suspended output. + virtual status_t restoreOutput(audio_io_handle_t output) = 0; + + // + // Audio input Control functions + // + + // opens an audio input + virtual audio_io_handle_t openInput(audio_module_handle_t module, audio_devices_t* pDevices, + uint32_t* pSamplingRate, audio_format_t* pFormat, + audio_channel_mask_t* pChannelMask) = 0; + // closes an audio input + virtual status_t closeInput(audio_io_handle_t input) = 0; + // + // misc control functions + // + + // set a stream volume for a particular output. For the same user setting, a given stream type + // can have different volumes for each output (destination device) it is attached to. + virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, + audio_io_handle_t output, int delayMs = 0) = 0; + + // invalidate a stream type, causing a reroute to an unspecified new output + virtual status_t invalidateStream(AudioSystem::stream_type stream) = 0; + + // function enabling to send proprietary informations directly from audio policy manager to + // audio hardware interface. + virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, + int delayMs = 0) = 0; + // function enabling to receive proprietary informations directly from audio hardware interface + // to audio policy manager. + virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) = 0; + + // request the playback of a tone on the specified stream: used for instance to replace + // notification sounds when playing over a telephony device during a phone call. + virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream) = 0; + virtual status_t stopTone() = 0; + + // set down link audio volume. + virtual status_t setVoiceVolume(float volume, int delayMs = 0) = 0; + + // move effect to the specified output + virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput, + audio_io_handle_t dstOutput) = 0; +}; + +extern "C" AudioPolicyInterface* createAudioPolicyManager( + AudioPolicyClientInterface* clientInterface); +extern "C" void destroyAudioPolicyManager(AudioPolicyInterface* interface); + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIOPOLICYINTERFACE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h new file mode 100644 index 0000000..ccc0d32 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioPolicyManagerBase.h @@ -0,0 +1,567 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android_audio_legacy { +using android::DefaultKeyedVector; +using android::KeyedVector; +using android::SortedVector; + +// ---------------------------------------------------------------------------- + +#define MAX_DEVICE_ADDRESS_LEN 20 +// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB +#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5 +// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB +#define SONIFICATION_HEADSET_VOLUME_MIN 0.016 +// Time in milliseconds during which we consider that music is still active after a music +// track was stopped - see computeVolume() +#define SONIFICATION_HEADSET_MUSIC_DELAY 5000 +// Time in milliseconds after media stopped playing during which we consider that the +// sonification should be as unobtrusive as during the time media was playing. +#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000 +// Time in milliseconds during witch some streams are muted while the audio path +// is switched +#define MUTE_TIME_MS 2000 + +#define NUM_TEST_OUTPUTS 5 + +#define NUM_VOL_CURVE_KNEES 2 + +// Default minimum length allowed for offloading a compressed track +// Can be overridden by the audio.offload.min.duration.secs property +#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60 + +// ---------------------------------------------------------------------------- +// AudioPolicyManagerBase implements audio policy manager behavior common to all platforms. +// Each platform must implement an AudioPolicyManager class derived from AudioPolicyManagerBase +// and override methods for which the platform specific behavior differs from the implementation +// in AudioPolicyManagerBase. Even if no specific behavior is required, the AudioPolicyManager +// class must be implemented as well as the class factory function createAudioPolicyManager() +// and provided in a shared library libaudiopolicy.so. +// ---------------------------------------------------------------------------- + +class AudioPolicyManagerBase : public AudioPolicyInterface +#ifdef AUDIO_POLICY_TEST + , + public Thread +#endif // AUDIO_POLICY_TEST +{ + + public: + AudioPolicyManagerBase(AudioPolicyClientInterface* clientInterface); + virtual ~AudioPolicyManagerBase(); + + // AudioPolicyInterface + virtual status_t setDeviceConnectionState(audio_devices_t device, + AudioSystem::device_connection_state state, + const char* device_address); + virtual AudioSystem::device_connection_state getDeviceConnectionState( + audio_devices_t device, const char* device_address); + virtual void setPhoneState(int state); + virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config); + virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage); + virtual void setSystemProperty(const char* property, const char* value); + virtual status_t initCheck(); + virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::output_flags flags, + const audio_offload_info_t* offloadInfo); + virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE); + virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, + audio_session_t session = AUDIO_SESSION_NONE); + virtual void releaseOutput(audio_io_handle_t output); + virtual audio_io_handle_t getInput(int inputSource, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + AudioSystem::audio_in_acoustics acoustics); + + // indicates to the audio policy manager that the input starts being used. + virtual status_t startInput(audio_io_handle_t input); + + // indicates to the audio policy manager that the input stops being used. + virtual status_t stopInput(audio_io_handle_t input); + virtual void releaseInput(audio_io_handle_t input); + virtual void closeAllInputs(); + virtual void initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax); + virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index, + audio_devices_t device); + virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int* index, + audio_devices_t device); + + // return the strategy corresponding to a given stream type + virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream); + + // return the enabled output devices for the given stream type + virtual audio_devices_t getDevicesForStream(AudioSystem::stream_type stream); + + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t* desc = NULL); + virtual status_t registerEffect(const effect_descriptor_t* desc, audio_io_handle_t io, + uint32_t strategy, audio_session_t session, int id); + virtual status_t unregisterEffect(int id); + virtual status_t setEffectEnabled(int id, bool enabled); + + virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const; + // return whether a stream is playing remotely, override to change the definition of + // local/remote playback, used for instance by notification manager to not make + // media players lose audio focus when not playing locally + virtual bool isStreamActiveRemotely(int stream, uint32_t inPastMs = 0) const; + virtual bool isSourceActive(audio_source_t source) const; + + virtual status_t dump(int fd); + + virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo); + + protected: + enum routing_strategy { + STRATEGY_MEDIA, + STRATEGY_PHONE, + STRATEGY_SONIFICATION, + STRATEGY_SONIFICATION_RESPECTFUL, + STRATEGY_DTMF, + STRATEGY_ENFORCED_AUDIBLE, + NUM_STRATEGIES + }; + + // 4 points to define the volume attenuation curve, each characterized by the volume + // index (from 0 to 100) at which they apply, and the attenuation in dB at that index. + // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl() + + enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4 }; + + class VolumeCurvePoint { + public: + int mIndex; + float mDBAttenuation; + }; + + // device categories used for volume curve management. + enum device_category { + DEVICE_CATEGORY_HEADSET, + DEVICE_CATEGORY_SPEAKER, + DEVICE_CATEGORY_EARPIECE, + DEVICE_CATEGORY_CNT + }; + + class IOProfile; + + class HwModule { + public: + HwModule(const char* name); + ~HwModule(); + + void dump(int fd); + + const char* const mName; // base name of the audio HW module (primary, a2dp ...) + audio_module_handle_t mHandle; + Vector mOutputProfiles; // output profiles exposed by this module + Vector mInputProfiles; // input profiles exposed by this module + }; + + // the IOProfile class describes the capabilities of an output or input stream. + // It is currently assumed that all combination of listed parameters are supported. + // It is used by the policy manager to determine if an output or input is suitable for + // a given use case, open/close it accordingly and connect/disconnect audio tracks + // to/from it. + class IOProfile { + public: + IOProfile(HwModule* module); + ~IOProfile(); + + bool isCompatibleProfile(audio_devices_t device, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + audio_output_flags_t flags) const; + + void dump(int fd); + void log(); + + // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats + // indicates the supported parameters should be read from the output stream + // after it is opened for the first time + Vector mSamplingRates; // supported sampling rates + Vector mChannelMasks; // supported channel masks + Vector mFormats; // supported audio formats + audio_devices_t mSupportedDevices; // supported devices (devices this output can be + // routed to) + audio_output_flags_t mFlags; // attribute flags (e.g primary output, + // direct output...). For outputs only. + HwModule* mModule; // audio HW module exposing this I/O stream + }; + + // default volume curve + static const VolumeCurvePoint sDefaultVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // default volume curve for media strategy + static const VolumeCurvePoint sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // volume curve for media strategy on speakers + static const VolumeCurvePoint sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // volume curve for sonification strategy on speakers + static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint + sSpeakerSonificationVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sHeadsetSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + // default volume curves per stream and device category. See initializeVolumeCurves() + static const VolumeCurvePoint* sVolumeProfiles[AudioSystem::NUM_STREAM_TYPES] + [DEVICE_CATEGORY_CNT]; + + // descriptor for audio outputs. Used to maintain current configuration of each opened audio + // output and keep track of the usage of this output by each audio stream type. + class AudioOutputDescriptor { + public: + AudioOutputDescriptor(const IOProfile* profile); + + status_t dump(int fd); + + audio_devices_t device() const; + void changeRefCount(AudioSystem::stream_type stream, int delta); + + bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); } + audio_devices_t supportedDevices(); + uint32_t latency(); + bool sharesHwModuleWith(const AudioOutputDescriptor* outputDesc); + bool isActive(uint32_t inPastMs = 0) const; + bool isStreamActive(AudioSystem::stream_type stream, uint32_t inPastMs = 0, + nsecs_t sysTime = 0) const; + bool isStrategyActive(routing_strategy strategy, uint32_t inPastMs = 0, + nsecs_t sysTime = 0) const; + + audio_io_handle_t mId; // output handle + uint32_t mSamplingRate; // + audio_format_t mFormat; // + audio_channel_mask_t mChannelMask; // output configuration + uint32_t mLatency; // + audio_output_flags_t mFlags; // + audio_devices_t mDevice; // current device this output is routed to + uint32_t mRefCount[AudioSystem::NUM_STREAM_TYPES]; // number of streams of each type using + // this output + nsecs_t mStopTime[AudioSystem::NUM_STREAM_TYPES]; + AudioOutputDescriptor* mOutput1; // used by duplicated outputs: first output + AudioOutputDescriptor* mOutput2; // used by duplicated outputs: second output + float mCurVolume[AudioSystem::NUM_STREAM_TYPES]; // current stream volume + int mMuteCount[AudioSystem::NUM_STREAM_TYPES]; // mute request counter + const IOProfile* mProfile; // I/O profile this output derives from + bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible + // device selection. See + // checkDeviceMuteStrategies() + uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) + bool mForceRouting; // Next routing for this output will be forced as current device routed + // is null + }; + + // descriptor for audio inputs. Used to maintain current configuration of each opened audio + // input and keep track of the usage of this input. + class AudioInputDescriptor { + public: + AudioInputDescriptor(const IOProfile* profile); + + status_t dump(int fd); + + audio_io_handle_t mId; // input handle + uint32_t mSamplingRate; // + audio_format_t mFormat; // input configuration + audio_channel_mask_t mChannelMask; // + audio_devices_t mDevice; // current device this input is routed to + uint32_t mRefCount; // number of AudioRecord clients using this output + int mInputSource; // input source selected by application (mediarecorder.h) + const IOProfile* mProfile; // I/O profile this output derives from + }; + + // stream descriptor used for volume control + class StreamDescriptor { + public: + StreamDescriptor(); + + int getVolumeIndex(audio_devices_t device); + void dump(int fd); + + int mIndexMin; // min volume index + int mIndexMax; // max volume index + KeyedVector mIndexCur; // current volume index per device + bool mCanBeMuted; // true is the stream can be muted + + const VolumeCurvePoint* mVolumeCurve[DEVICE_CATEGORY_CNT]; + }; + + // stream descriptor used for volume control + class EffectDescriptor { + public: + status_t dump(int fd); + + int mIo; // io the effect is attached to + routing_strategy mStrategy; // routing strategy the effect is associated to + audio_session_t mSession; // audio session the effect is on + effect_descriptor_t mDesc; // effect descriptor + bool mEnabled; // enabled state: CPU load being used or not + }; + + void addOutput(audio_io_handle_t id, AudioOutputDescriptor* outputDesc); + void addInput(audio_io_handle_t id, AudioInputDescriptor* inputDesc); + + // return the strategy corresponding to a given stream type + static routing_strategy getStrategy(AudioSystem::stream_type stream); + + // return appropriate device for streams handled by the specified strategy according to current + // phone state, connected devices... + // if fromCache is true, the device is returned from mDeviceForStrategy[], + // otherwise it is determine by current state + // (device connected,phone state, force use, a2dp output...) + // This allows to: + // 1 speed up process when the state is stable (when starting or stopping an output) + // 2 access to either current device selection (fromCache == true) or + // "future" device selection (fromCache == false) when called from a context + // where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND + // before updateDevicesAndOutputs() is called. + virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache); + + // change the route of the specified output. Returns the number of ms we have slept to + // allow new routing to take effect in certain cases. + uint32_t setOutputDevice(audio_io_handle_t output, audio_devices_t device, bool force = false, + int delayMs = 0); + + // select input device corresponding to requested audio source + virtual audio_devices_t getDeviceForInputSource(int inputSource); + + // return io handle of active input or 0 if no input is active + // Only considers inputs from physical devices (e.g. main mic, headset mic) when + // ignoreVirtualInputs is true. + audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true); + + // initialize volume curves for each strategy and device category + void initializeVolumeCurves(); + + // compute the actual volume for a given stream according to the requested index and a + // particular device + virtual float computeVolume(int stream, int index, audio_io_handle_t output, + audio_devices_t device); + + // check that volume change is permitted, compute and send new volume to audio hardware + status_t checkAndSetVolume(int stream, int index, audio_io_handle_t output, + audio_devices_t device, int delayMs = 0, bool force = false); + + // apply all stream volumes to the specified output and device + void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, + bool force = false); + + // Mute or unmute all streams handled by the specified strategy on the specified output + void setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, + int delayMs = 0, audio_devices_t device = (audio_devices_t)0); + + // Mute or unmute the stream on the specified output + void setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs = 0, + audio_devices_t device = (audio_devices_t)0); + + // handle special cases for sonification strategy while in call: mute streams or replace by + // a special tone in the device used for communication + void handleIncallSonification(int stream, bool starting, bool stateChange); + + // true if device is in a telephony or VoIP call + virtual bool isInCall(); + + // true if given state represents a device in a telephony or VoIP call + virtual bool isStateInCall(int state); + + // when a device is connected, checks if an open output can be routed + // to this device. If none is open, tries to open one of the available outputs. + // Returns an output suitable to this device or 0. + // when a device is disconnected, checks if an output is not used any more and + // returns its handle if any. + // transfers the audio tracks and effects from one output thread to another accordingly. + status_t checkOutputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector& outputs, + const String8 paramStr); + + status_t checkInputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector& inputs, const String8 paramStr); + + // close an output and its companion duplicating output. + void closeOutput(audio_io_handle_t output); + + // checks and if necessary changes outputs used for all strategies. + // must be called every time a condition that affects the output choice for a given strategy + // changes: connected device, phone state, force use... + // Must be called before updateDevicesAndOutputs() + void checkOutputForStrategy(routing_strategy strategy); + + // Same as checkOutputForStrategy() but for a all strategies in order of priority + void checkOutputForAllStrategies(); + + // manages A2DP output suspend/restore according to phone state and BT SCO usage + void checkA2dpSuspend(); + + // returns the A2DP output handle if it is open or 0 otherwise + audio_io_handle_t getA2dpOutput(); + + // selects the most appropriate device on output for current state + // must be called every time a condition that affects the device choice for a given output is + // changed: connected device, phone state, force use, output start, output stop.. + // see getDeviceForStrategy() for the use of fromCache parameter + + audio_devices_t getNewDevice(audio_io_handle_t output, bool fromCache); + // updates cache of device used by all strategies (mDeviceForStrategy[]) + // must be called every time a condition that affects the device choice for a given strategy is + // changed: connected device, phone state, force use... + // cached values are used by getDeviceForStrategy() if parameter fromCache is true. + // Must be called after checkOutputForAllStrategies() + + void updateDevicesAndOutputs(); + + virtual uint32_t getMaxEffectsCpuLoad(); + virtual uint32_t getMaxEffectsMemory(); +#ifdef AUDIO_POLICY_TEST + virtual bool threadLoop(); + void exit(); + int testOutputIndex(audio_io_handle_t output); +#endif // AUDIO_POLICY_TEST + + status_t setEffectEnabled(EffectDescriptor* pDesc, bool enabled); + + // returns the category the device belongs to with regard to volume curve management + static device_category getDeviceCategory(audio_devices_t device); + + // extract one device relevant for volume control from multiple device selection + static audio_devices_t getDeviceForVolume(audio_devices_t device); + + SortedVector getOutputsForDevice( + audio_devices_t device, + DefaultKeyedVector openOutputs); + bool vectorsEqual(SortedVector& outputs1, + SortedVector& outputs2); + + // mute/unmute strategies using an incompatible device combination + // if muting, wait for the audio in pcm buffer to be drained before proceeding + // if unmuting, unmute only after the specified delay + // Returns the number of ms waited + uint32_t checkDeviceMuteStrategies(AudioOutputDescriptor* outputDesc, + audio_devices_t prevDevice, uint32_t delayMs); + + audio_io_handle_t selectOutput(const SortedVector& outputs, + AudioSystem::output_flags flags); + IOProfile* getInputProfile(audio_devices_t device, uint32_t samplingRate, audio_format_t format, + audio_channel_mask_t channelMask); + IOProfile* getProfileForDirectOutput(audio_devices_t device, uint32_t samplingRate, + audio_format_t format, audio_channel_mask_t channelMask, + audio_output_flags_t flags); + + audio_io_handle_t selectOutputForEffects(const SortedVector& outputs); + + bool isNonOffloadableEffectEnabled(); + + // + // Audio policy configuration file parsing (audio_policy.conf) + // + static uint32_t stringToEnum(const struct StringToEnum* table, size_t size, const char* name); + static bool stringToBool(const char* value); + static audio_output_flags_t parseFlagNames(char* name); + static audio_devices_t parseDeviceNames(char* name); + void loadSamplingRates(char* name, IOProfile* profile); + void loadFormats(char* name, IOProfile* profile); + void loadOutChannels(char* name, IOProfile* profile); + void loadInChannels(char* name, IOProfile* profile); + status_t loadOutput(cnode* root, HwModule* module); + status_t loadInput(cnode* root, HwModule* module); + void loadHwModule(cnode* root); + void loadHwModules(cnode* root); + void loadGlobalConfig(cnode* root); + status_t loadAudioPolicyConfig(const char* path); + void defaultAudioPolicyConfig(void); + + AudioPolicyClientInterface* mpClientInterface; // audio policy client interface + audio_io_handle_t mPrimaryOutput; // primary output handle + // list of descriptors for outputs currently opened + DefaultKeyedVector mOutputs; + // copy of mOutputs before setDeviceConnectionState() opens new outputs + // reset to mOutputs when updateDevicesAndOutputs() is called. + DefaultKeyedVector mPreviousOutputs; + + // list of input descriptors currently opened + DefaultKeyedVector mInputs; + + audio_devices_t mAvailableOutputDevices; // bit field of all available output devices + audio_devices_t mAvailableInputDevices; // bit field of all available input devices + // without AUDIO_DEVICE_BIT_IN to allow direct bit + // field comparisons + int mPhoneState; // current phone state + AudioSystem::forced_config + mForceUse[AudioSystem::NUM_FORCE_USE]; // current forced use configuration + + StreamDescriptor + mStreams[AudioSystem::NUM_STREAM_TYPES]; // stream descriptors for volume control + String8 mA2dpDeviceAddress; // A2DP device MAC address + String8 mScoDeviceAddress; // SCO device MAC address + String8 mUsbOutCardAndDevice; // USB audio ALSA card and device numbers: + // card=;device=<> + bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected + audio_devices_t mDeviceForStrategy[NUM_STRATEGIES]; + float mLastVoiceVolume; // last voice volume value sent to audio HAL + + // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units + static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000; + // Maximum memory allocated to audio effects in KB + static const uint32_t MAX_EFFECTS_MEMORY = 512; + uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects + uint32_t mTotalEffectsMemory; // current memory used by effects + KeyedVector mEffects; // list of registered audio effects + bool mA2dpSuspended; // true if A2DP output is suspended + bool mHasA2dp; // true on platforms with support for bluetooth A2DP + bool mHasUsb; // true on platforms with support for USB audio + bool mHasRemoteSubmix; // true on platforms with support for remote presentation of a submix + audio_devices_t mAttachedOutputDevices; // output devices always available on the platform + audio_devices_t mDefaultOutputDevice; // output device selected by default at boot time + // (must be in mAttachedOutputDevices) + bool mSpeakerDrcEnabled; // true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path + // to boost soft sounds, used to adjust volume curves accordingly + + Vector mHwModules; + +#ifdef AUDIO_POLICY_TEST + Mutex mLock; + Condition mWaitWorkCV; + + int mCurOutput; + bool mDirectOutput; + audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS]; + int mTestInput; + uint32_t mTestDevice; + uint32_t mTestSamplingRate; + uint32_t mTestFormat; + uint32_t mTestChannels; + uint32_t mTestLatencyMs; +#endif // AUDIO_POLICY_TEST + + private: + static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, + int indexInUi); + // updates device caching and output for streams that can influence the + // routing of notifications + void handleNotificationRoutingForStream(AudioSystem::stream_type stream); + static bool isVirtualInputDevice(audio_devices_t device); +}; + +}; // namespace android_audio_legacy diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h new file mode 100644 index 0000000..943b0db --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/AudioSystemLegacy.h @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2008 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_AUDIOSYSTEM_LEGACY_H_ +#define ANDROID_AUDIOSYSTEM_LEGACY_H_ + +#include +#include +#include + +#include +#include + +namespace android_audio_legacy { + +using android::AudioParameter; +using android::status_t; + +enum { + OK = android::OK, + NO_ERROR = android::NO_ERROR, + + UNKNOWN_ERROR = android::UNKNOWN_ERROR, + + NO_MEMORY = android::NO_MEMORY, + INVALID_OPERATION = android::INVALID_OPERATION, + BAD_VALUE = android::BAD_VALUE, + BAD_TYPE = android::BAD_TYPE, + NAME_NOT_FOUND = android::NAME_NOT_FOUND, + PERMISSION_DENIED = android::PERMISSION_DENIED, + NO_INIT = android::NO_INIT, + ALREADY_EXISTS = android::ALREADY_EXISTS, + DEAD_OBJECT = android::DEAD_OBJECT, + FAILED_TRANSACTION = android::FAILED_TRANSACTION, + BAD_INDEX = android::BAD_INDEX, + NOT_ENOUGH_DATA = android::NOT_ENOUGH_DATA, + WOULD_BLOCK = android::WOULD_BLOCK, + TIMED_OUT = android::TIMED_OUT, + UNKNOWN_TRANSACTION = android::UNKNOWN_TRANSACTION, +}; + +enum audio_source { + AUDIO_SOURCE_DEFAULT = 0, + AUDIO_SOURCE_MIC = 1, + AUDIO_SOURCE_VOICE_UPLINK = 2, + AUDIO_SOURCE_VOICE_DOWNLINK = 3, + AUDIO_SOURCE_VOICE_CALL = 4, + AUDIO_SOURCE_CAMCORDER = 5, + AUDIO_SOURCE_VOICE_RECOGNITION = 6, + AUDIO_SOURCE_VOICE_COMMUNICATION = 7, + AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_COMMUNICATION, + + AUDIO_SOURCE_LIST_END // must be last - used to validate audio source type +}; + +class AudioSystem { + public: +#if 1 + enum stream_type { + DEFAULT = -1, + VOICE_CALL = 0, + SYSTEM = 1, + RING = 2, + MUSIC = 3, + ALARM = 4, + NOTIFICATION = 5, + BLUETOOTH_SCO = 6, + ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker + DTMF = 8, + TTS = 9, + NUM_STREAM_TYPES + }; + + // Audio sub formats (see AudioSystem::audio_format). + enum pcm_sub_format { + PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility + PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility + }; + + enum audio_sessions { + SESSION_OUTPUT_STAGE = AUDIO_SESSION_OUTPUT_STAGE, + SESSION_OUTPUT_MIX = AUDIO_SESSION_OUTPUT_MIX, + }; + + // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to + // specify bit rate, stereo mode, version... + enum mp3_sub_format { + // TODO + }; + + // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient + // or octet aligned, encoding mode for recording... + enum amr_sub_format { + // TODO + }; + + // AAC sub format field definition: specify profile or bitrate for recording... + enum aac_sub_format { + // TODO + }; + + // VORBIS sub format field definition: specify quality for recording... + enum vorbis_sub_format { + // TODO + }; + + // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 + // bits). The main format indicates the main codec type. The sub format field indicates options + // and parameters for each format. The sub format is mainly used for record to indicate for + // instance the requested bitrate or profile. It can also be used for certain formats to give + // informations not present in the encoded audio stream (e.g. octet alignement for AMR). + enum audio_format { + INVALID_FORMAT = -1, + FORMAT_DEFAULT = 0, + PCM = 0x00000000, // must be 0 for backward compatibility + MP3 = 0x01000000, + AMR_NB = 0x02000000, + AMR_WB = 0x03000000, + AAC = 0x04000000, + HE_AAC_V1 = 0x05000000, + HE_AAC_V2 = 0x06000000, + VORBIS = 0x07000000, + MAIN_FORMAT_MASK = 0xFF000000, + SUB_FORMAT_MASK = 0x00FFFFFF, + // Aliases + PCM_16_BIT = (PCM | PCM_SUB_16_BIT), + PCM_8_BIT = (PCM | PCM_SUB_8_BIT) + }; + + enum audio_channels { + // output channels + CHANNEL_OUT_FRONT_LEFT = 0x1, + CHANNEL_OUT_FRONT_RIGHT = 0x2, + CHANNEL_OUT_FRONT_CENTER = 0x4, + CHANNEL_OUT_LOW_FREQUENCY = 0x8, + CHANNEL_OUT_BACK_LEFT = 0x10, + CHANNEL_OUT_BACK_RIGHT = 0x20, + CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40, + CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80, + CHANNEL_OUT_BACK_CENTER = 0x100, + CHANNEL_OUT_SIDE_LEFT = 0x200, + CHANNEL_OUT_SIDE_RIGHT = 0x400, + CHANNEL_OUT_TOP_CENTER = 0x800, + CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000, + CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000, + CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000, + CHANNEL_OUT_TOP_BACK_LEFT = 0x8000, + CHANNEL_OUT_TOP_BACK_CENTER = 0x10000, + CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000, + + CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT, + CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT), + CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), + CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER), + CHANNEL_OUT_5POINT1 = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), + // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1 + CHANNEL_OUT_7POINT1 = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT), + CHANNEL_OUT_ALL = + (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | + CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | + CHANNEL_OUT_BACK_CENTER | CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT | + CHANNEL_OUT_TOP_CENTER | CHANNEL_OUT_TOP_FRONT_LEFT | + CHANNEL_OUT_TOP_FRONT_CENTER | CHANNEL_OUT_TOP_FRONT_RIGHT | + CHANNEL_OUT_TOP_BACK_LEFT | CHANNEL_OUT_TOP_BACK_CENTER | + CHANNEL_OUT_TOP_BACK_RIGHT), + + // input channels + CHANNEL_IN_LEFT = 0x4, + CHANNEL_IN_RIGHT = 0x8, + CHANNEL_IN_FRONT = 0x10, + CHANNEL_IN_BACK = 0x20, + CHANNEL_IN_LEFT_PROCESSED = 0x40, + CHANNEL_IN_RIGHT_PROCESSED = 0x80, + CHANNEL_IN_FRONT_PROCESSED = 0x100, + CHANNEL_IN_BACK_PROCESSED = 0x200, + CHANNEL_IN_PRESSURE = 0x400, + CHANNEL_IN_X_AXIS = 0x800, + CHANNEL_IN_Y_AXIS = 0x1000, + CHANNEL_IN_Z_AXIS = 0x2000, + CHANNEL_IN_VOICE_UPLINK = 0x4000, + CHANNEL_IN_VOICE_DNLINK = 0x8000, + CHANNEL_IN_MONO = CHANNEL_IN_FRONT, + CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT), + CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK | + CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | + CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED | + CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | + CHANNEL_IN_Z_AXIS | CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK) + }; + + enum audio_mode { + MODE_INVALID = -2, + MODE_CURRENT = -1, + MODE_NORMAL = 0, + MODE_RINGTONE, + MODE_IN_CALL, + MODE_IN_COMMUNICATION, + NUM_MODES // not a valid entry, denotes end-of-list + }; + + enum audio_in_acoustics { + AGC_ENABLE = 0x0001, + AGC_DISABLE = 0, + NS_ENABLE = 0x0002, + NS_DISABLE = 0, + TX_IIR_ENABLE = 0x0004, + TX_DISABLE = 0 + }; + + // DO NOT USE: the "audio_devices" enumeration below is obsolete, use type "audio_devices_t" and + // audio device enumeration from system/audio.h instead. + enum audio_devices { + // output devices + DEVICE_OUT_EARPIECE = 0x1, + DEVICE_OUT_SPEAKER = 0x2, + DEVICE_OUT_WIRED_HEADSET = 0x4, + DEVICE_OUT_WIRED_HEADPHONE = 0x8, + DEVICE_OUT_BLUETOOTH_SCO = 0x10, + DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, + DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, + DEVICE_OUT_BLUETOOTH_A2DP = 0x80, + DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, + DEVICE_OUT_AUX_DIGITAL = 0x400, + DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800, + DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000, + DEVICE_OUT_DEFAULT = 0x8000, + DEVICE_OUT_ALL = + (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | + DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | + DEVICE_OUT_BLUETOOTH_SCO_HEADSET | DEVICE_OUT_BLUETOOTH_SCO_CARKIT | + DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | + DEVICE_OUT_ANLG_DOCK_HEADSET | DEVICE_OUT_DGTL_DOCK_HEADSET | DEVICE_OUT_DEFAULT), + DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), + + // input devices + DEVICE_IN_COMMUNICATION = 0x10000, + DEVICE_IN_AMBIENT = 0x20000, + DEVICE_IN_BUILTIN_MIC = 0x40000, + DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000, + DEVICE_IN_WIRED_HEADSET = 0x100000, + DEVICE_IN_AUX_DIGITAL = 0x200000, + DEVICE_IN_VOICE_CALL = 0x400000, + DEVICE_IN_BACK_MIC = 0x800000, + DEVICE_IN_DEFAULT = 0x80000000, + + DEVICE_IN_ALL = + (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC | + DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL | + DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT) + }; + + // request to open a direct output with getOutput() (by opposition to sharing an output with + // other AudioTracks) + enum output_flags { OUTPUT_FLAG_INDIRECT = 0x0, OUTPUT_FLAG_DIRECT = 0x1 }; + + // device categories used for setForceUse() + enum forced_config { + FORCE_NONE, + FORCE_SPEAKER, + FORCE_HEADPHONES, + FORCE_BT_SCO, + FORCE_BT_A2DP, + FORCE_WIRED_ACCESSORY, + FORCE_BT_CAR_DOCK, + FORCE_BT_DESK_DOCK, + FORCE_ANALOG_DOCK, + FORCE_DIGITAL_DOCK, + FORCE_NO_BT_A2DP, + FORCE_SYSTEM_ENFORCED, + NUM_FORCE_CONFIG, + FORCE_DEFAULT = FORCE_NONE + }; + + // usages used for setForceUse() + enum force_use { + FOR_COMMUNICATION, + FOR_MEDIA, + FOR_RECORD, + FOR_DOCK, + FOR_SYSTEM, + NUM_FORCE_USE + }; + + // + // AudioPolicyService interface + // + + // device connection states used for setDeviceConnectionState() + enum device_connection_state { + DEVICE_STATE_UNAVAILABLE, + DEVICE_STATE_AVAILABLE, + NUM_DEVICE_STATES + }; + +#endif + + static uint32_t popCount(uint32_t u) { return popcount(u); } + +#if 1 + static bool isOutputDevice(audio_devices device) { + if ((popcount(device) == 1) && ((device & ~DEVICE_OUT_ALL) == 0)) + return true; + else + return false; + } + static bool isInputDevice(audio_devices device) { + if ((popcount(device) == 1) && ((device & ~DEVICE_IN_ALL) == 0)) + return true; + else + return false; + } + static bool isA2dpDevice(audio_devices device) { + return audio_is_a2dp_device((audio_devices_t)device); + } + static bool isBluetoothScoDevice(audio_devices device) { + return audio_is_bluetooth_sco_device((audio_devices_t)device); + } + static bool isValidFormat(uint32_t format) { + return audio_is_valid_format((audio_format_t)format); + } + static bool isLinearPCM(uint32_t format) { return audio_is_linear_pcm((audio_format_t)format); } + static bool isOutputChannel(audio_channel_mask_t channel) { + return audio_is_output_channel(channel); + } + static bool isInputChannel(audio_channel_mask_t channel) { + return audio_is_input_channel(channel); + } + +#endif +}; + +}; // namespace android_audio_legacy + +#endif // ANDROID_AUDIOSYSTEM_LEGACY_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h new file mode 100644 index 0000000..158ff59 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/IMountService.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +// +#ifndef ANDROID_HARDWARE_IMOUNTSERVICE_H +#define ANDROID_HARDWARE_IMOUNTSERVICE_H + +#include +#include + +namespace android { + +// ---------------------------------------------------------------------- + +class IMountService : public IInterface { + public: + static const int OperationSucceeded = 0; + static const int OperationFailedInternalError = -1; + static const int OperationFailedNoMedia = -2; + static const int OperationFailedMediaBlank = -3; + static const int OperationFailedMediaCorrupt = -4; + static const int OperationFailedVolumeNotMounted = -5; + + public: + DECLARE_META_INTERFACE(MountService); + + virtual void getShareMethodList() = 0; + virtual bool getShareMethodAvailable(String16 method) = 0; + virtual int shareVolume(String16 path, String16 method) = 0; + virtual int unshareVolume(String16 path, String16 method) = 0; + virtual bool getVolumeShared(String16 path, String16 method) = 0; + virtual int mountVolume(String16 path) = 0; + virtual int unmountVolume(String16 path) = 0; + virtual int formatVolume(String16 path) = 0; + virtual String16 getVolumeState(String16 mountPoint) = 0; + virtual int createSecureContainer(String16 id, int sizeMb, String16 fstype, String16 key, + int ownerUid) = 0; + virtual int finalizeSecureContainer(String16 id) = 0; + virtual int destroySecureContainer(String16 id) = 0; + virtual int mountSecureContainer(String16 id, String16 key, int ownerUid) = 0; + virtual int unmountSecureContainer(String16 id) = 0; + virtual int renameSecureContainer(String16 oldId, String16 newId) = 0; + virtual String16 getSecureContainerPath(String16 id) = 0; + virtual void getSecureContainerList() = 0; + virtual void shutdown() = 0; +}; + +// ---------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_HARDWARE_IMOUNTSERVICE_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h new file mode 100644 index 0000000..13d62f9 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/audio_policy_conf.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 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_AUDIO_POLICY_CONF_H +#define ANDROID_AUDIO_POLICY_CONF_H + +///////////////////////////////////////////////// +// Definitions for audio policy configuration file (audio_policy.conf) +///////////////////////////////////////////////// + +#define AUDIO_HARDWARE_MODULE_ID_MAX_LEN 32 + +#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf" +#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf" + +// global configuration +#define GLOBAL_CONFIG_TAG "global_configuration" + +#define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices" +#define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device" +#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices" +#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled" + +// hw modules descriptions +#define AUDIO_HW_MODULE_TAG "audio_hw_modules" + +#define OUTPUTS_TAG "outputs" +#define INPUTS_TAG "inputs" + +#define SAMPLING_RATES_TAG "sampling_rates" +#define FORMATS_TAG "formats" +#define CHANNELS_TAG "channel_masks" +#define DEVICES_TAG "devices" +#define FLAGS_TAG "flags" + +#define DYNAMIC_VALUE_TAG \ + "dynamic" // special value for "channel_masks", "sampling_rates" and + // "formats" in outputs descriptors indicating that supported + // values should be queried after opening the output. + +#endif // ANDROID_AUDIO_POLICY_CONF_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h new file mode 100644 index 0000000..c6c52c6 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/gscan.h @@ -0,0 +1,427 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_GSCAN_H__ +#define __WIFI_HAL_GSCAN_H__ + +// Define static_assert() unless already defined by compiler. +#ifndef __has_feature +#define __has_feature(__x) 0 +#endif +#if !(__has_feature(cxx_static_assert)) && !defined(static_assert) +#define static_assert(__b, __m) \ + extern int compile_time_assert_failed[(__b) ? 1 : -1] __attribute__((unused)); +#endif + +/* AP Scans */ + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, // 2.4 GHz + WIFI_BAND_A = 2, // 5 GHz without DFS + WIFI_BAND_A_DFS = 4, // 5 GHz DFS only + WIFI_BAND_A_WITH_DFS = 6, // 5 GHz with DFS + WIFI_BAND_ABG = 3, // 2.4 GHz + 5 GHz; no DFS + WIFI_BAND_ABG_WITH_DFS = 7, // 2.4 GHz + 5 GHz with DFS +} wifi_band; + +#define MAX_CHANNELS 16 +#define MAX_BUCKETS 16 +#define MAX_HOTLIST_APS 128 +#define MAX_SIGNIFICANT_CHANGE_APS 64 +#define MAX_EPNO_NETWORKS 64 +#define MAX_HOTLIST_SSID 8 +#define MAX_AP_CACHE_PER_SCAN 32 + +wifi_error wifi_get_valid_channels(wifi_interface_handle handle, int band, int max_channels, + wifi_channel* channels, int* num_channels); + +typedef struct { + int max_scan_cache_size; // total space allocated for scan (in bytes) + int max_scan_buckets; // maximum number of channel buckets + int max_ap_cache_per_scan; // maximum number of APs that can be stored per scan + int max_rssi_sample_size; // number of RSSI samples used for averaging RSSI + int max_scan_reporting_threshold; // max possible report_threshold as described + // in wifi_scan_cmd_params + int max_hotlist_bssids; // maximum number of entries for hotlist BSSIDs + int max_hotlist_ssids; // maximum number of entries for hotlist SSIDs + int max_significant_wifi_change_aps; // maximum number of entries for + // significant wifi change APs + int max_bssid_history_entries; // number of BSSID/RSSI entries that device can hold + int max_number_epno_networks; // max number of epno entries + int max_number_epno_networks_by_ssid; // max number of epno entries if ssid is specified, + // that is, epno entries for which an exact match is + // required, or entries corresponding to hidden ssids + int max_number_of_white_listed_ssid; // max number of white listed SSIDs, M target is 2 to 4 +} wifi_gscan_capabilities; + +wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, + wifi_gscan_capabilities* capabilities); + +typedef enum { + WIFI_SCAN_RESULTS_AVAILABLE, // reported when REPORT_EVENTS_EACH_SCAN is set and a scan + // completes. WIFI_SCAN_THRESHOLD_NUM_SCANS or + // WIFI_SCAN_THRESHOLD_PERCENT can be reported instead if the + // reason for the event is available; however, at most one of + // these events should be reported per scan. If there are + // multiple buckets that were scanned this period and one has the + // EACH_SCAN flag set then this event should be prefered. + WIFI_SCAN_THRESHOLD_NUM_SCANS, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and + // report_threshold_num_scans is reached. + WIFI_SCAN_THRESHOLD_PERCENT, // can be reported when REPORT_EVENTS_EACH_SCAN is not set and + // report_threshold_percent is reached. + WIFI_SCAN_FAILED, // reported when currently executing gscans have failed. + // start_gscan will need to be called again in order to continue + // scanning. This is intended to indicate abnormal scan + // terminations (not those as a result of stop_gscan). +} wifi_scan_event; + +/* Format of information elements found in the beacon */ +typedef struct { + byte id; // element identifier + byte len; // number of bytes to follow + byte data[]; +} wifi_information_element; + +typedef struct { + wifi_timestamp ts; // time since boot (in microsecond) when the result was + // retrieved + char ssid[32 + 1]; // null terminated + mac_addr bssid; + wifi_channel channel; // channel frequency in MHz + wifi_rssi rssi; // in db + wifi_timespan rtt; // in nanoseconds + wifi_timespan rtt_sd; // standard deviation in rtt + unsigned short beacon_period; // period advertised in the beacon + unsigned short capability; // capabilities advertised in the beacon + unsigned int ie_length; // size of the ie_data blob + char ie_data[1]; // blob of all the information elements found in the + // beacon; this data should be a packed list of + // wifi_information_element objects, one after the other. + // other fields +} wifi_scan_result; + +static_assert( + MAX_BUCKETS <= 8 * sizeof(unsigned), + "The buckets_scanned bitset is represented by an unsigned int and cannot support this many " + "buckets on this platform."); +typedef struct { + /* reported when each probe response is received, if report_events + * enabled in wifi_scan_cmd_params. buckets_scanned is a bitset of the + * buckets that are currently being scanned. See the buckets_scanned field + * in the wifi_cached_scan_results struct for more details. + */ + void (*on_full_scan_result)(wifi_request_id id, wifi_scan_result* result, + unsigned buckets_scanned); + + /* indicates progress of scanning statemachine */ + void (*on_scan_event)(wifi_request_id id, wifi_scan_event event); + +} wifi_scan_result_handler; + +typedef struct { + wifi_channel channel; // frequency + int dwellTimeMs; // dwell time hint + int passive; // 0 => active, 1 => passive scan; ignored for DFS + /* Add channel class */ +} wifi_scan_channel_spec; + +#define REPORT_EVENTS_EACH_SCAN (1 << 0) +#define REPORT_EVENTS_FULL_RESULTS (1 << 1) +#define REPORT_EVENTS_NO_BATCH (1 << 2) + +typedef struct { + int bucket; // bucket index, 0 based + wifi_band band; // when UNSPECIFIED, use channel list + int period; // desired period, in millisecond; if this is too + // low, the firmware should choose to generate results as + // fast as it can instead of failing the command. + // for exponential backoff bucket this is the min_period + /* report_events semantics - + * This is a bit field; which defines following bits - + * REPORT_EVENTS_EACH_SCAN => report a scan completion event after scan. If this is not set + * then scan completion events should be reported if + * report_threshold_percent or report_threshold_num_scans is + * reached. + * REPORT_EVENTS_FULL_RESULTS => forward scan results (beacons/probe responses + IEs) + * in real time to HAL, in addition to completion events + * Note: To keep backward compatibility, fire completion + * events regardless of REPORT_EVENTS_EACH_SCAN. + * REPORT_EVENTS_NO_BATCH => controls if scans for this bucket should be placed in the + * history buffer + */ + byte report_events; + int max_period; // if max_period is non zero or different than period, then this bucket is + // an exponential backoff bucket and the scan period will grow exponentially + // as per formula: actual_period(N) = period * (base ^ (N/step_count)) + // to a maximum period of max_period + int base; // for exponential back off bucket: multiplier: new_period=old_period*base + int step_count; // for exponential back off bucket, number of scans to perform for a given + // period + + int num_channels; + // channels to scan; these may include DFS channels + // Note that a given channel may appear in multiple buckets + wifi_scan_channel_spec channels[MAX_CHANNELS]; +} wifi_scan_bucket_spec; + +typedef struct { + int base_period; // base timer period in ms + int max_ap_per_scan; // number of access points to store in each scan entry in + // the BSSID/RSSI history buffer (keep the highest RSSI + // access points) + int report_threshold_percent; // in %, when scan buffer is this much full, wake up apps + // processor + int report_threshold_num_scans; // in number of scans, wake up AP after these many scans + int num_buckets; + wifi_scan_bucket_spec buckets[MAX_BUCKETS]; +} wifi_scan_cmd_params; + +/* + * Start periodic GSCAN + * When this is called all requested buckets should be scanned, starting the beginning of the cycle + * + * For example: + * If there are two buckets specified + * - Bucket 1: period=10s + * - Bucket 2: period=20s + * - Bucket 3: period=30s + * Then the following scans should occur + * - t=0 buckets 1, 2, and 3 are scanned + * - t=10 bucket 1 is scanned + * - t=20 bucket 1 and 2 are scanned + * - t=30 bucket 1 and 3 are scanned + * - t=40 bucket 1 and 2 are scanned + * - t=50 bucket 1 is scanned + * - t=60 buckets 1, 2, and 3 are scanned + * - and the patter repeats + * + * If any scan does not occur or is incomplete (error, interrupted, etc) then a cached scan result + * should still be recorded with the WIFI_SCAN_FLAG_INTERRUPTED flag set. + */ +wifi_error wifi_start_gscan(wifi_request_id id, wifi_interface_handle iface, + wifi_scan_cmd_params params, wifi_scan_result_handler handler); + +/* Stop periodic GSCAN */ +wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface); + +typedef enum { + WIFI_SCAN_FLAG_INTERRUPTED = 1 // Indicates that scan results are not complete because + // probes were not sent on some channels +} wifi_scan_flags; + +/* Get the GSCAN cached scan results */ +typedef struct { + int scan_id; // a unique identifier for the scan unit + int flags; // a bitmask with additional + // information about scan. + unsigned buckets_scanned; // a bitset of the buckets that were scanned. + // for example a value of 13 (0b1101) would + // indicate that buckets 0, 2 and 3 were + // scanned to produce this list of results. + // should be set to 0 if this information is + // not available. + int num_results; // number of bssids retrieved by the scan + wifi_scan_result results[MAX_AP_CACHE_PER_SCAN]; // scan results - one for each bssid +} wifi_cached_scan_results; + +wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, int max, + wifi_cached_scan_results* results, int* num); + +/* BSSID Hotlist */ +typedef struct { + void (*on_hotlist_ap_found)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); + void (*on_hotlist_ap_lost)(wifi_request_id id, unsigned num_results, wifi_scan_result* results); +} wifi_hotlist_ap_found_handler; + +typedef struct { + mac_addr bssid; // AP BSSID + wifi_rssi low; // low threshold + wifi_rssi high; // high threshold +} ap_threshold_param; + +typedef struct { + int lost_ap_sample_size; + int num_bssid; // number of hotlist APs + ap_threshold_param ap[MAX_HOTLIST_APS]; // hotlist APs +} wifi_bssid_hotlist_params; + +/* Set the BSSID Hotlist */ +wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, + wifi_bssid_hotlist_params params, + wifi_hotlist_ap_found_handler handler); + +/* Clear the BSSID Hotlist */ +wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface); + +/* SSID Hotlist */ +typedef struct { + void (*on_hotlist_ssid_found)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); + void (*on_hotlist_ssid_lost)(wifi_request_id id, unsigned num_results, + wifi_scan_result* results); +} wifi_hotlist_ssid_handler; + +typedef struct { + char ssid[32 + 1]; // SSID + wifi_band band; // band for this set of threshold params + wifi_rssi low; // low threshold + wifi_rssi high; // high threshold +} ssid_threshold_param; + +typedef struct { + int lost_ssid_sample_size; + int num_ssid; // number of hotlist SSIDs + ssid_threshold_param ssid[MAX_HOTLIST_SSID]; // hotlist SSIDs +} wifi_ssid_hotlist_params; + +/* Significant wifi change */ +typedef struct { + mac_addr bssid; // BSSID + wifi_channel channel; // channel frequency in MHz + int num_rssi; // number of rssi samples + wifi_rssi rssi[]; // RSSI history in db +} wifi_significant_change_result; + +typedef struct { + void (*on_significant_change)(wifi_request_id id, unsigned num_results, + wifi_significant_change_result** results); +} wifi_significant_change_handler; + +// The sample size parameters in the wifi_significant_change_params structure +// represent the number of occurence of a g-scan where the BSSID was seen and RSSI was +// collected for that BSSID, or, the BSSID was expected to be seen and didn't. +// for instance: lost_ap_sample_size : number of time a g-scan was performed on the +// channel the BSSID was seen last, and the BSSID was not seen during those g-scans +typedef struct { + int rssi_sample_size; // number of samples for averaging RSSI + int lost_ap_sample_size; // number of samples to confirm AP loss + int min_breaching; // number of APs breaching threshold + int num_bssid; // max 64 + ap_threshold_param ap[MAX_SIGNIFICANT_CHANGE_APS]; +} wifi_significant_change_params; + +/* Set the Signifcant AP change list */ +wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_significant_change_params params, + wifi_significant_change_handler handler); + +/* Clear the Signifcant AP change list */ +wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface); + +/* Random MAC OUI for PNO */ +wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui); + +// Enhanced PNO: +// Enhanced PNO feature is expected to be enabled all of the time (e.g. screen lit) and may thus +// require firmware to store a large number of networks, covering the whole list of known networks. +// Therefore, it is acceptable for firmware to store a crc24, crc32 or other short hash of the SSID, +// such that a low but non-zero probability of collision exist. With that scheme it should be +// possible for firmware to keep an entry as small as 4 bytes for each pno network. +// For instance, a firmware pn0 entry can be implemented in the form of: +// PNO ENTRY = crc24(3 bytes) | flags>>3 (5 bits) | auth flags(3 bits) +// +// No scans should be automatically performed by the chip. Instead all scan results from gscan +// should be scored and the wifi_epno_handler on_network_found callback should be called with +// the scan results. +// +// A PNO network shall be reported once, that is, once a network is reported by firmware +// its entry shall be marked as "done" until framework calls wifi_set_epno_list again. +// Calling wifi_set_epno_list shall reset the "done" status of pno networks in firmware. +// +// A network should only be considered found if its RSSI is above the minimum RSSI for its +// frequency range (min5GHz_rssi and min24GHz_rssi for 5GHz and 2.4GHz networks respectively). +// When disconnected the list of scan results should be returned if any network is found. +// When connected the scan results shall be reported only if the score of any network in the scan +// is greater than that of the currently connected BSSID. +// +// The FW should calculate the score of all the candidates (including currently connected one) +// with following equation: +// RSSI score = (RSSI + 85) * 4; +// If RSSI score > initial_score_max , RSSI score = initial_score_max; +// final score = RSSI score +// + current_connection_bonus (if currently connected BSSID) +// + same_network_bonus (if network has SAME_NETWORK flag) +// + secure_bonus (if the network is not open) +// + band5GHz_bonus (if BSSID is on 5G) +// If there is a BSSID’s score > current BSSID’s score, then report the cached scan results +// at the end of the scan (excluding the ones on blacklist) to the upper layer. +// Additionally, all BSSIDs that are in the BSSID blacklist should be ignored by Enhanced PNO + +// Whether directed scan needs to be performed (for hidden SSIDs) +#define WIFI_PNO_FLAG_DIRECTED_SCAN (1 << 0) +// Whether PNO event shall be triggered if the network is found on A band +#define WIFI_PNO_FLAG_A_BAND (1 << 1) +// Whether PNO event shall be triggered if the network is found on G band +#define WIFI_PNO_FLAG_G_BAND (1 << 2) +// Whether strict matching is required +// If required then the firmware must store the network's SSID and not just a hash +#define WIFI_PNO_FLAG_STRICT_MATCH (1 << 3) +// If this SSID should be considered the same network as the currently connected one for scoring +#define WIFI_PNO_FLAG_SAME_NETWORK (1 << 4) + +// Code for matching the beacon AUTH IE - additional codes TBD +#define WIFI_PNO_AUTH_CODE_OPEN (1 << 0) // open +#define WIFI_PNO_AUTH_CODE_PSK (1 << 1) // WPA_PSK or WPA2PSK +#define WIFI_PNO_AUTH_CODE_EAPOL (1 << 2) // any EAPOL + +typedef struct { + char ssid[32 + 1]; // null terminated + byte flags; // WIFI_PNO_FLAG_XXX + byte auth_bit_field; // auth bit field for matching WPA IE +} wifi_epno_network; + +/* ePNO Parameters */ +typedef struct { + int min5GHz_rssi; // minimum 5GHz RSSI for a BSSID to be considered + int min24GHz_rssi; // minimum 2.4GHz RSSI for a BSSID to be considered + int initial_score_max; // the maximum score that a network can have before bonuses + int current_connection_bonus; // only report when there is a network's score this much higher + // than the current connection. + int same_network_bonus; // score bonus for all networks with the same network flag + int secure_bonus; // score bonus for networks that are not open + int band5GHz_bonus; // 5GHz RSSI score bonus (applied to all 5GHz networks) + int num_networks; // number of wifi_epno_network objects + wifi_epno_network networks[MAX_EPNO_NETWORKS]; // PNO networks +} wifi_epno_params; + +typedef struct { + // on results + void (*on_network_found)(wifi_request_id id, unsigned num_results, wifi_scan_result* results); +} wifi_epno_handler; + +/* Set the ePNO list - enable ePNO with the given parameters */ +wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface, + const wifi_epno_params* epno_params, wifi_epno_handler handler); + +/* Reset the ePNO list - no ePNO networks should be matched after this */ +wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface); + +typedef struct { + int id; // identifier of this network block, report this in event + char realm[256]; // null terminated UTF8 encoded realm, 0 if unspecified + int64_t roamingConsortiumIds[16]; // roaming consortium ids to match, 0s if unspecified + byte plmn[3]; // mcc/mnc combination as per rules, 0s if unspecified +} wifi_passpoint_network; + +typedef struct { + void (*on_passpoint_network_found)( + wifi_request_id id, + int net_id, // network block identifier for the matched network + wifi_scan_result* result, // scan result, with channel and beacon information + int anqp_len, // length of ANQP blob + byte* anqp // ANQP data, in the information_element format + ); +} wifi_passpoint_event_handler; + +/* Sets a list for passpoint networks for PNO purposes; it should be matched + * against any passpoint networks (designated by Interworking element) found + * during regular PNO scan. */ +wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, + wifi_passpoint_network* networks, + wifi_passpoint_event_handler handler); + +/* Reset passpoint network list - no Passpoint networks should be matched after this */ +wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface); + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h new file mode 100644 index 0000000..7585cdf --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/link_layer_stats.h @@ -0,0 +1,285 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_STATS_H +#define __WIFI_HAL_STATS_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define STATS_MAJOR_VERSION 1 +#define STATS_MINOR_VERSION 0 +#define STATS_MICRO_VERSION 0 + +typedef enum { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, // if done by firmware/driver + WIFI_EAPOL_COMPLETED = 5, // if done by firmware/driver +} wifi_connection_state; + +typedef enum { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} wifi_roam_state; + +typedef enum { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_TDLS = 7, + WIFI_INTERFACE_UNKNOWN = -1 +} wifi_interface_mode; + +#define WIFI_CAPABILITY_QOS 0x00000001 // set for QOS association +#define WIFI_CAPABILITY_PROTECTED \ + 0x00000002 // set for protected association (802.11 beacon frame control protected bit set) +#define WIFI_CAPABILITY_INTERWORKING \ + 0x00000004 // set if 802.11 Extended Capabilities element interworking bit is set +#define WIFI_CAPABILITY_HS20 0x00000008 // set for HS20 association +#define WIFI_CAPABILITY_SSID_UTF8 \ + 0x00000010 // set is 802.11 Extended Capabilities element UTF-8 SSID bit is set +#define WIFI_CAPABILITY_COUNTRY 0x00000020 // set is 802.11 Country Element is present + +typedef struct { + wifi_interface_mode mode; // interface mode + u8 mac_addr[6]; // interface mac address (self) + wifi_connection_state state; // connection state (valid for STA, CLI only) + wifi_roam_state roaming; // roaming state + u32 capabilities; // WIFI_CAPABILITY_XXX (self) + u8 ssid[33]; // null terminated SSID + u8 bssid[6]; // bssid + u8 ap_country_str[3]; // country string advertised by AP + u8 country_str[3]; // country string for this association + u8 time_slicing_duty_cycle_percent; // if this iface is being served using time slicing on a + // radio with one or more ifaces (i.e MCC), then the duty + // cycle assigned to this iface in %. If not using time + // slicing (i.e SCC or DBS), set to 100. +} wifi_interface_link_layer_info; + +/* channel information */ +typedef struct { + wifi_channel_width width; // channel width (20, 40, 80, 80+80, 160, 320) + wifi_channel center_freq; // primary 20 MHz channel + wifi_channel center_freq0; // center frequency (MHz) first segment + wifi_channel center_freq1; // center frequency (MHz) second segment +} wifi_channel_info; + +/* wifi rate */ +typedef struct { + u32 preamble : 3; // 0: OFDM, 1:CCK, 2:HT 3:VHT 4:HE 5:EHT 6..7 reserved + u32 nss : 2; // 0:1x1, 1:2x2, 3:3x3, 4:4x4 + u32 bw : 3; // 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz 4:320Mhz + u32 rateMcsIdx : 8; // OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps + // HT/VHT/HE/EHT it would be mcs index + u32 reserved : 16; // reserved + u32 bitrate; // units of 100 Kbps +} wifi_rate; + +/* channel statistics */ +typedef struct { + wifi_channel_info channel; // channel + u32 on_time; // msecs the radio is awake (32 bits number accruing over time) + u32 cca_busy_time; // msecs the CCA register is busy (32 bits number accruing over time) +} wifi_channel_stat; + +// Max number of tx power levels. The actual number vary per device and is specified by +// |num_tx_levels| +#define RADIO_STAT_MAX_TX_LEVELS 256 + +/* radio statistics */ +typedef struct { + wifi_radio radio; // wifi radio (if multiple radio supported) + u32 on_time; // msecs the radio is awake (32 bits number accruing over time) + u32 tx_time; // msecs the radio is transmitting (32 bits number accruing over time) + u32 num_tx_levels; // number of radio transmit power levels + u32* tx_time_per_levels; // pointer to an array of radio transmit per power levels in + // msecs accured over time + u32 rx_time; // msecs the radio is in active receive (32 bits number accruing over time) + u32 on_time_scan; // msecs the radio is awake due to all scan (32 bits number accruing over + // time) + u32 on_time_nbd; // msecs the radio is awake due to NAN (32 bits number accruing over time) + u32 on_time_gscan; // msecs the radio is awake due to G?scan (32 bits number accruing over + // time) + u32 on_time_roam_scan; // msecs the radio is awake due to roam?scan (32 bits number accruing + // over time) + u32 on_time_pno_scan; // msecs the radio is awake due to PNO scan (32 bits number accruing over + // time) + u32 on_time_hs20; // msecs the radio is awake due to HS2.0 scans and GAS exchange (32 bits + // number accruing over time) + u32 num_channels; // number of channels + wifi_channel_stat channels[]; // channel statistics +} wifi_radio_stat; + +/** + * Packet statistics reporting by firmware is performed on MPDU basi (i.e. counters increase by 1 + * for each MPDU) As well, "data packet" in associated comments, shall be interpreted as 802.11 data + * packet, that is, 802.11 frame control subtype == 2 and excluding management and control frames. + * + * As an example, in the case of transmission of an MSDU fragmented in 16 MPDUs which are + * transmitted OTA in a 16 units long a-mpdu, for which a block ack is received with 5 bits set: + * tx_mpdu : shall increase by 5 + * retries : shall increase by 16 + * tx_ampdu : shall increase by 1 + * data packet counters shall not increase regardless of the number of BAR potentially sent by + * device for this a-mpdu data packet counters shall not increase regardless of the number of BA + * received by device for this a-mpdu + * + * For each subsequent retransmission of the 11 remaining non ACK'ed mpdus + * (regardless of the fact that they are transmitted in a-mpdu or not) + * retries : shall increase by 1 + * + * If no subsequent BA or ACK are received from AP, until packet lifetime expires for those 11 + * packet that were not ACK'ed mpdu_lost : shall increase by 11 + */ + +/* per rate statistics */ +typedef struct { + wifi_rate rate; // rate information + u32 tx_mpdu; // number of successfully transmitted data pkts (ACK rcvd) + u32 rx_mpdu; // number of received data pkts + u32 mpdu_lost; // number of data packet losses (no ACK) + u32 retries; // total number of data pkt retries + u32 retries_short; // number of short data pkt retries + u32 retries_long; // number of long data pkt retries +} wifi_rate_stat; + +/* access categories */ +typedef enum { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} wifi_traffic_ac; + +/* wifi peer type */ +typedef enum { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} wifi_peer_type; + +/* per peer statistics */ +typedef struct bssload_info { + u16 sta_count; // station count + u16 chan_util; // channel utilization + u8 PAD[4]; +} bssload_info_t; + +typedef struct { + wifi_peer_type type; // peer type (AP, TDLS, GO etc.) + u8 peer_mac_address[6]; // mac address + u32 capabilities; // peer WIFI_CAPABILITY_XXX + bssload_info_t bssload; // STA count and CU + u32 num_rate; // number of rates + wifi_rate_stat rate_stats[]; // per rate statistics, number of entries = num_rate +} wifi_peer_info; + +/* Per access category statistics */ +typedef struct { + wifi_traffic_ac ac; // access category (VI, VO, BE, BK) + u32 tx_mpdu; // number of successfully transmitted unicast data pkts (ACK rcvd) + u32 rx_mpdu; // number of received unicast data packets + u32 tx_mcast; // number of succesfully transmitted multicast data packets + // STA case: implies ACK received from AP for the unicast packet in which mcast + // pkt was sent + u32 rx_mcast; // number of received multicast data packets + u32 rx_ampdu; // number of received unicast a-mpdus; support of this counter is optional + u32 tx_ampdu; // number of transmitted unicast a-mpdus; support of this counter is optional + u32 mpdu_lost; // number of data pkt losses (no ACK) + u32 retries; // total number of data pkt retries + u32 retries_short; // number of short data pkt retries + u32 retries_long; // number of long data pkt retries + u32 contention_time_min; // data pkt min contention time (usecs) + u32 contention_time_max; // data pkt max contention time (usecs) + u32 contention_time_avg; // data pkt avg contention time (usecs) + u32 contention_num_samples; // num of data pkts used for contention statistics +} wifi_wmm_ac_stat; + +/* interface statistics */ +typedef struct { + wifi_interface_handle iface; // wifi interface + wifi_interface_link_layer_info info; // current state of the interface + u32 beacon_rx; // access point beacon received count from connected AP + u64 average_tsf_offset; // average beacon offset encountered (beacon_TSF - TBTT) + // The average_tsf_offset field is used so as to calculate the + // typical beacon contention time on the channel as well may be + // used to debug beacon synchronization and related power consumption + // issue + u32 leaky_ap_detected; // indicate that this AP typically leaks packets beyond the driver guard + // time. + u32 leaky_ap_avg_num_frames_leaked; // average number of frame leaked by AP after frame with PM + // bit set was ACK'ed by AP + u32 leaky_ap_guard_time; // guard time currently in force (when implementing IEEE power + // management based on frame control PM bit), How long driver waits + // before shutting down the radio and after receiving an ACK for a + // data frame with PM bit set) + u32 mgmt_rx; // access point mgmt frames received count from connected AP (including Beacon) + u32 mgmt_action_rx; // action frames received count + u32 mgmt_action_tx; // action frames transmit count + wifi_rssi rssi_mgmt; // access Point Beacon and Management frames RSSI (averaged) + wifi_rssi rssi_data; // access Point Data Frames RSSI (averaged) from connected AP + wifi_rssi rssi_ack; // access Point ACK RSSI (averaged) from connected AP + wifi_wmm_ac_stat ac[WIFI_AC_MAX]; // per ac data packet statistics + u32 num_peers; // number of peers + wifi_peer_info peer_info[]; // per peer statistics +} wifi_iface_stat; + +/* configuration params */ +typedef struct { + u32 mpdu_size_threshold; // threshold to classify the pkts as short or long + // packet size < mpdu_size_threshold => short + u32 aggressive_statistics_gathering; // set for field debug mode. Driver should collect all + // statistics regardless of performance impact. +} wifi_link_layer_params; + +/* API to trigger the link layer statistics collection. + Unless his API is invoked - link layer statistics will not be collected. + Radio statistics (once started) do not stop or get reset unless wifi_clear_link_stats is invoked + Interface statistics (once started) reset and start afresh after each connection */ +wifi_error wifi_set_link_stats(wifi_interface_handle iface, wifi_link_layer_params params); + +/* callback for reporting link layer stats */ +typedef struct { + void (*on_link_stats_results)(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios, + wifi_radio_stat* radio_stat); +} wifi_stats_result_handler; + +/* api to collect the link layer statistics for a given iface and all the radio stats */ +wifi_error wifi_get_link_stats(wifi_request_id id, wifi_interface_handle iface, + wifi_stats_result_handler handler); + +/* wifi statistics bitmap */ +#define WIFI_STATS_RADIO 0x00000001 // all radio statistics +#define WIFI_STATS_RADIO_CCA 0x00000002 // cca_busy_time (within radio statistics) +#define WIFI_STATS_RADIO_CHANNELS 0x00000004 // all channel statistics (within radio statistics) +#define WIFI_STATS_RADIO_SCAN 0x00000008 // all scan statistics (within radio statistics) +#define WIFI_STATS_IFACE 0x00000010 // all interface statistics +#define WIFI_STATS_IFACE_TXRATE 0x00000020 // all tx rate statistics (within interface statistics) +#define WIFI_STATS_IFACE_AC 0x00000040 // all ac statistics (within interface statistics) +#define WIFI_STATS_IFACE_CONTENTION \ + 0x00000080 // all contention (min, max, avg) statistics (within ac statisctics) + +/* clear api to reset statistics, stats_clear_rsp_mask identifies what stats have been cleared + stop_req = 1 will imply whether to stop the statistics collection. + stop_rsp = 1 will imply that stop_req was honored and statistics collection was stopped. + */ +wifi_error wifi_clear_link_stats(wifi_interface_handle iface, u32 stats_clear_req_mask, + u32* stats_clear_rsp_mask, u8 stop_req, u8* stop_rsp); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_STATS_ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h new file mode 100644 index 0000000..2b6d12a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/power.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008 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 _HARDWARE_POWER_H +#define _HARDWARE_POWER_H + +#include + +#if __cplusplus +extern "C" { +#endif + +enum { + PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off + FULL_WAKE_LOCK = 2 // the screen is also on +}; + +// while you have a lock held, the device will stay on at least at the +// level you request. +int acquire_wake_lock(int lock, const char* id); +int release_wake_lock(const char* id); + +#if __cplusplus +} // extern "C" +#endif + +#endif // _HARDWARE_POWER_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h new file mode 100644 index 0000000..3369e3e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/roam.h @@ -0,0 +1,57 @@ +/* + * 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 __WIFI_HAL_ROAM_H__ +#define __WIFI_HAL_ROAM_H__ + +#include "wifi_hal.h" + +#define MAX_BLACKLIST_BSSID 16 +#define MAX_WHITELIST_SSID 8 +#define MAX_SSID_LENGTH 32 + +typedef struct { + u32 max_blacklist_size; + u32 max_whitelist_size; +} wifi_roaming_capabilities; + +typedef enum { ROAMING_DISABLE, ROAMING_ENABLE } fw_roaming_state_t; + +typedef struct { + u32 length; + char ssid_str[MAX_SSID_LENGTH]; +} ssid_t; + +typedef struct { + u32 num_blacklist_bssid; // Number of bssids valid in blacklist_bssid[]. + mac_addr blacklist_bssid[MAX_BLACKLIST_BSSID]; // List of bssids which should not be considered + // for romaing by firmware/driver. + u32 num_whitelist_ssid; // Number of ssids valid in whitelist_ssid[]. + ssid_t whitelist_ssid[MAX_WHITELIST_SSID]; // List of ssids to which firmware/driver can + // consider to roam to. +} wifi_roaming_config; + +/* Get the chipset roaming capabilities. */ +wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle, + wifi_roaming_capabilities* caps); +/* Enable/disable firmware roaming */ +wifi_error wifi_enable_firmware_roaming(wifi_interface_handle handle, fw_roaming_state_t state); + +/* Pass down the blacklist BSSID and whitelist SSID to firmware. */ +wifi_error wifi_configure_roaming(wifi_interface_handle handle, + wifi_roaming_config* roaming_config); + +#endif /* __WIFI_HAL_ROAM_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h new file mode 100644 index 0000000..8be7fd3 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/rtt.h @@ -0,0 +1,314 @@ + +#include "gscan.h" +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_RTT_H__ +#define __WIFI_HAL_RTT_H__ + +/* Ranging status */ +typedef enum { + RTT_STATUS_SUCCESS = 0, + RTT_STATUS_FAILURE = 1, // general failure status + RTT_STATUS_FAIL_NO_RSP = 2, // target STA does not respond to request + RTT_STATUS_FAIL_REJECTED = 3, // request rejected. Applies to 2-sided RTT only + RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4, + RTT_STATUS_FAIL_TM_TIMEOUT = 5, // timing measurement times out + RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6, // Target on different channel, cannot range + RTT_STATUS_FAIL_NO_CAPABILITY = 7, // ranging not supported + RTT_STATUS_ABORTED = 8, // request aborted for unknown reason + RTT_STATUS_FAIL_INVALID_TS = 9, // Invalid T1-T4 timestamp + RTT_STATUS_FAIL_PROTOCOL = 10, // 11mc protocol failed + RTT_STATUS_FAIL_SCHEDULE = 11, // request could not be scheduled + RTT_STATUS_FAIL_BUSY_TRY_LATER = 12, // responder cannot collaborate at time of request + RTT_STATUS_INVALID_REQ = 13, // bad request args + RTT_STATUS_NO_WIFI = 14, // WiFi not enabled + RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = + 15, // Responder overrides param info, cannot range with new params + RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE = 16, // Negotiation failure + RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17, // concurrency not supported (NDP+RTT) +} wifi_rtt_status; + +/* RTT peer type */ +typedef enum { + RTT_PEER_AP = 0x1, + RTT_PEER_STA = 0x2, + RTT_PEER_P2P_GO = 0x3, + RTT_PEER_P2P_CLIENT = 0x4, + RTT_PEER_NAN = 0x5 +} rtt_peer_type; + +/* RTT Measurement Bandwidth */ +typedef enum { + WIFI_RTT_BW_5 = 0x01, + WIFI_RTT_BW_10 = 0x02, + WIFI_RTT_BW_20 = 0x04, + WIFI_RTT_BW_40 = 0x08, + WIFI_RTT_BW_80 = 0x10, + WIFI_RTT_BW_160 = 0x20, + WIFI_RTT_BW_320 = 0x40 +} wifi_rtt_bw; + +/* RTT Measurement Preamble */ +typedef enum { + WIFI_RTT_PREAMBLE_LEGACY = 0x1, + WIFI_RTT_PREAMBLE_HT = 0x2, + WIFI_RTT_PREAMBLE_VHT = 0x4, + WIFI_RTT_PREAMBLE_HE = 0x8, + WIFI_RTT_PREAMBLE_EHT = 0x10, +} wifi_rtt_preamble; + +/* RTT Type */ +typedef enum { + RTT_TYPE_1_SIDED = 0x1, + RTT_TYPE_2_SIDED = 0x2, +} wifi_rtt_type; + +/* RTT configuration */ +typedef struct { + mac_addr addr; // peer device mac address + wifi_rtt_type type; // 1-sided or 2-sided RTT + rtt_peer_type peer; // optional - peer device hint (STA, P2P, AP) + wifi_channel_info channel; // Required for STA-AP mode, optional for P2P, NBD etc. + unsigned burst_period; // Time interval between bursts (units: 100 ms). + // Applies to 1-sided and 2-sided RTT multi-burst requests. + // Range: 0-31, 0: no preference by initiator (2-sided RTT) + unsigned num_burst; // Total number of RTT bursts to be executed. It will be + // specified in the same way as the parameter "Number of + // Burst Exponent" found in the FTM frame format. It + // applies to both: 1-sided RTT and 2-sided RTT. Valid + // values are 0 to 15 as defined in 802.11mc std. + // 0 means single shot + // The implication of this parameter on the maximum + // number of RTT results is the following: + // for 1-sided RTT: max num of RTT results = + // (2^num_burst)*(num_frames_per_burst) for 2-sided RTT: max num of RTT + // results = (2^num_burst)*(num_frames_per_burst - 1) + unsigned num_frames_per_burst; // num of frames per burst. + // Minimum value = 1, Maximum value = 31 + // For 2-sided this equals the number of FTM frames + // to be attempted in a single burst. This also + // equals the number of FTM frames that the + // initiator will request that the responder send + // in a single frame. + unsigned + num_retries_per_rtt_frame; // number of retries for a failed RTT frame. Applies + // to 1-sided RTT only. Minimum value = 0, Maximum value = 3 + + // following fields are only valid for 2-side RTT + unsigned num_retries_per_ftmr; // Maximum number of retries that the initiator can + // retry an FTMR frame. + // Minimum value = 0, Maximum value = 3 + byte LCI_request; // 1: request LCI, 0: do not request LCI + byte LCR_request; // 1: request LCR, 0: do not request LCR + unsigned burst_duration; // Applies to 1-sided and 2-sided RTT. Valid values will + // be 2-11 and 15 as specified by the 802.11mc std for + // the FTM parameter burst duration. In a multi-burst + // request, if responder overrides with larger value, + // the initiator will return failure. In a single-burst + // request if responder overrides with larger value, + // the initiator will sent TMR_STOP to terminate RTT + // at the end of the burst_duration it requested. + wifi_rtt_preamble preamble; // RTT preamble to be used in the RTT frames + wifi_rtt_bw bw; // RTT BW to be used in the RTT frames +} wifi_rtt_config; + +/* RTT results */ +typedef struct { + mac_addr addr; // device mac address + unsigned burst_num; // burst number in a multi-burst request + unsigned measurement_number; // Total RTT measurement frames attempted + unsigned success_number; // Total successful RTT measurement frames + byte number_per_burst_peer; // Maximum number of "FTM frames per burst" supported by + // the responder STA. Applies to 2-sided RTT only. + // If reponder overrides with larger value: + // - for single-burst request initiator will truncate the + // larger value and send a TMR_STOP after receiving as + // many frames as originally requested. + // - for multi-burst request, initiator will return + // failure right away. + wifi_rtt_status status; // ranging status + byte retry_after_duration; // When status == RTT_STATUS_FAIL_BUSY_TRY_LATER, + // this will be the time provided by the responder as to + // when the request can be tried again. Applies to 2-sided + // RTT only. In sec, 1-31sec. + wifi_rtt_type type; // RTT type + wifi_rssi rssi; // average rssi in 0.5 dB steps e.g. 143 implies -71.5 dB + wifi_rssi rssi_spread; // rssi spread in 0.5 dB steps e.g. 5 implies 2.5 dB spread (optional) + wifi_rate tx_rate; // 1-sided RTT: TX rate of RTT frame. + // 2-sided RTT: TX rate of initiator's Ack in response to FTM frame. + wifi_rate rx_rate; // 1-sided RTT: TX rate of Ack from other side. + // 2-sided RTT: TX rate of FTM frame coming from responder. + wifi_timespan rtt; // round trip time in picoseconds + wifi_timespan rtt_sd; // rtt standard deviation in picoseconds + wifi_timespan rtt_spread; // difference between max and min rtt times recorded in picoseconds + int distance_mm; // distance in mm (optional) + int distance_sd_mm; // standard deviation in mm (optional) + int distance_spread_mm; // difference between max and min distance recorded in mm (optional) + wifi_timestamp ts; // time of the measurement (in microseconds since boot) + int burst_duration; // in ms, actual time taken by the FW to finish one burst + // measurement. Applies to 1-sided and 2-sided RTT. + int negotiated_burst_num; // Number of bursts allowed by the responder. Applies + // to 2-sided RTT only. + wifi_information_element* LCI; // for 11mc only + wifi_information_element* LCR; // for 11mc only +} wifi_rtt_result; + +/* RTT result callback */ +typedef struct { + void (*on_rtt_results)(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_result[]); +} wifi_rtt_event_handler; + +/* API to request RTT measurement */ +wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, + unsigned num_rtt_config, wifi_rtt_config rtt_config[], + wifi_rtt_event_handler handler); + +/* API to cancel RTT measurements */ +wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, + unsigned num_devices, mac_addr addr[]); + +/* NBD ranging channel map */ +typedef struct { + wifi_channel availablity[32]; // specifies the channel map for each of the 16 TU windows + // frequency of 0 => unspecified; which means firmware is + // free to do whatever it wants in this window. +} wifi_channel_map; + +/* API to start publishing the channel map on responder device in a NBD cluster. + Responder device will take this request and schedule broadcasting the channel map + in a NBD ranging attribute in a SDF. DE will automatically remove the ranging + attribute from the OTA queue after number of DW specified by num_dw + where Each DW is 512 TUs apart */ +wifi_error wifi_rtt_channel_map_set(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_map* params, unsigned num_dw); + +/* API to clear the channel map on the responder device in a NBD cluster. + Responder device will cancel future ranging channel request, starting from “next” + DW interval and will also stop broadcasting NBD ranging attribute in SDF */ +wifi_error wifi_rtt_channel_map_clear(wifi_request_id id, wifi_interface_handle iface); + +// Preamble definition for bit mask used in wifi_rtt_capabilities +#define PREAMBLE_LEGACY 0x1 +#define PREAMBLE_HT 0x2 +#define PREAMBLE_VHT 0x4 +#define PREAMBLE_HE 0x8 +#define PREAMBLE_EHT 0x10 + +// BW definition for bit mask used in wifi_rtt_capabilities +#define BW_5_SUPPORT 0x1 +#define BW_10_SUPPORT 0x2 +#define BW_20_SUPPORT 0x4 +#define BW_40_SUPPORT 0x8 +#define BW_80_SUPPORT 0x10 +#define BW_160_SUPPORT 0x20 +#define BW_320_SUPPORT 0x40 + +/* RTT Capabilities */ +typedef struct { + byte rtt_one_sided_supported; // if 1-sided rtt data collection is supported + byte rtt_ftm_supported; // if ftm rtt data collection is supported + byte lci_support; // if initiator supports LCI request. Applies to 2-sided RTT + byte lcr_support; // if initiator supports LCR request. Applies to 2-sided RTT + byte preamble_support; // bit mask indicates what preamble is supported by initiator + byte bw_support; // bit mask indicates what BW is supported by initiator + byte responder_supported; // if 11mc responder mode is supported + byte mc_version; // draft 11mc spec version supported by chip. For instance, + // version 4.0 should be 40 and version 4.3 should be 43 etc. +} wifi_rtt_capabilities; + +/* RTT capabilities of the device */ +wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, + wifi_rtt_capabilities* capabilities); + +/* debugging definitions */ +enum { + RTT_DEBUG_DISABLE, + RTT_DEBUG_LOG, + RTT_DEBUG_PROTO, + RTT_DEBUG_BURST, + RTT_DEBUG_ACCURACY, + RTT_DEBUG_LOGDETAIL +}; // rtt debug type + +enum { RTT_DEBUG_FORMAT_TXT, RTT_DEBUG_FORMAT_BINARY }; // rtt debug format + +typedef struct rtt_debug { + unsigned version; + unsigned len; // total length of after len field + unsigned type; // rtt debug type + unsigned format; // rtt debug format + char dbuf[0]; // debug content +} rtt_debug_t; + +/* set configuration for debug */ +wifi_error wifi_rtt_debug_cfg(wifi_interface_handle h, unsigned rtt_dbg_type, char* cfgbuf, + unsigned cfg_buf_size); +/* get the debug information */ +wifi_error wifi_rtt_debug_get(wifi_interface_handle h, rtt_debug_t** debugbuf); +/* free the debug buffer */ +wifi_error wifi_rtt_debug_free(wifi_interface_handle h, rtt_debug_t* debugbuf); + +/* API for setting LCI/LCR information to be provided to a requestor */ +typedef enum { + WIFI_MOTION_NOT_EXPECTED = 0, // Not expected to change location + WIFI_MOTION_EXPECTED = 1, // Expected to change location + WIFI_MOTION_UNKNOWN = 2, // Movement pattern unknown +} wifi_motion_pattern; + +typedef struct { + long latitude; // latitude in degrees * 2^25 , 2's complement + long longitude; // latitude in degrees * 2^25 , 2's complement + int altitude; // Altitude in units of 1/256 m + byte latitude_unc; // As defined in Section 2.3.2 of IETF RFC 6225 + byte longitude_unc; // As defined in Section 2.3.2 of IETF RFC 6225 + byte altitude_unc; // As defined in Section 2.4.5 from IETF RFC 6225: + + // Following element for configuring the Z subelement + wifi_motion_pattern motion_pattern; + int floor; // floor in units of 1/16th of floor. 0x80000000 if unknown. + int height_above_floor; // in units of 1/64 m + int height_unc; // in units of 1/64 m. 0 if unknown +} wifi_lci_information; + +typedef struct { + char country_code[2]; // country code + int length; // length of the info field + char civic_info[256]; // Civic info to be copied in FTM frame +} wifi_lcr_information; + +// API to configure the LCI. Used in RTT Responder mode only +wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface, wifi_lci_information* lci); + +// API to configure the LCR. Used in RTT Responder mode only. +wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface, wifi_lcr_information* lcr); + +/** + * RTT Responder information + */ +typedef struct { + wifi_channel_info channel; + wifi_rtt_preamble preamble; +} wifi_rtt_responder; + +/** + * Get RTT responder information e.g. WiFi channel to enable responder on. + */ +wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface, + wifi_rtt_responder* responder_info); + +/** + * Enable RTT responder mode. + * channel_hint - hint of the channel information where RTT responder should be enabled on. + * max_duration_seconds - timeout of responder mode. + * channel_used - channel used for RTT responder, NULL if responder is not enabled. + */ +wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_info channel_hint, unsigned max_duration_seconds, + wifi_rtt_responder* responder_info); + +/** + * Disable RTT responder mode. + */ +wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface); + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h new file mode 100644 index 0000000..787b13a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/tdls.h @@ -0,0 +1,84 @@ + +#include "wifi_hal.h" + +#ifndef _TDLS_H_ +#define _TDLS_H_ + +typedef enum { + WIFI_TDLS_DISABLED = 1, /* TDLS is not enabled, default status for all STAs */ + WIFI_TDLS_ENABLED, /* TDLS is enabled, but not yet tried */ + WIFI_TDLS_ESTABLISHED, /* Direct link is established */ + WIFI_TDLS_ESTABLISHED_OFF_CHANNEL, /* Direct link is established using MCC */ + WIFI_TDLS_DROPPED, /* Direct link was established, + * but is temporarily dropped now */ + WIFI_TDLS_FAILED /* TDLS permanent failed. Inform error to upper layer + * and go back to WIFI_TDLS_DISABLED */ +} wifi_tdls_state; + +typedef enum { + WIFI_TDLS_SUCCESS, /* Success */ + WIFI_TDLS_UNSPECIFIED = -1, /* Unspecified reason */ + WIFI_TDLS_NOT_SUPPORTED = -2, /* Remote side doesn't support TDLS */ + WIFI_TDLS_UNSUPPORTED_BAND = -3, /* Remote side doesn't support this band */ + WIFI_TDLS_NOT_BENEFICIAL = -4, /* Going to AP is better than going direct */ + WIFI_TDLS_DROPPED_BY_REMOTE = -5 /* Remote side doesn't want it anymore */ +} wifi_tdls_reason; + +typedef struct { + int channel; /* channel hint, in channel number (NOT frequency ) */ + int global_operating_class; /* operating class to use */ + int max_latency_ms; /* max latency that can be tolerated by apps */ + int min_bandwidth_kbps; /* bandwidth required by apps, in kilo bits per second */ +} wifi_tdls_params; + +typedef struct { + int channel; + int global_operating_class; + wifi_tdls_state state; + wifi_tdls_reason reason; +} wifi_tdls_status; + +typedef struct { + int max_concurrent_tdls_session_num; /* Maximum TDLS session number can be supported by the + * Firmware and hardware*/ + int is_global_tdls_supported; /* 1 -- support, 0 -- not support */ + int is_per_mac_tdls_supported; /* 1 -- support, 0 -- not support */ + int is_off_channel_tdls_supported; /* 1 -- support, 0 -- not support */ +} wifi_tdls_capabilities; + +typedef struct { + /* on_tdls_state_changed - reports state of TDLS link to framework + * Report this event when the state of TDLS link changes */ + void (*on_tdls_state_changed)(mac_addr addr, wifi_tdls_status status); +} wifi_tdls_handler; + +/* wifi_enable_tdls - enables TDLS-auto mode for a specific route + * + * params specifies hints, which provide more information about + * why TDLS is being sought. The firmware should do its best to + * honor the hints before downgrading regular AP link + * If upper layer has no specific values, this should be NULL + * + * handler is used to inform the upper layer about the status change and the corresponding reason + */ +wifi_error wifi_enable_tdls(wifi_interface_handle iface, mac_addr addr, wifi_tdls_params* params, + wifi_tdls_handler handler); + +/* wifi_disable_tdls - disables TDLS-auto mode for a specific route + * + * This terminates any existing TDLS with addr device, and frees the + * device resources to make TDLS connections on new routes. + * + * DON'T fire any more events on 'handler' specified in earlier call to + * wifi_enable_tdls after this action. + */ +wifi_error wifi_disable_tdls(wifi_interface_handle iface, mac_addr addr); + +/* wifi_get_tdls_status - allows getting the status of TDLS for a specific route */ +wifi_error wifi_get_tdls_status(wifi_interface_handle iface, mac_addr addr, + wifi_tdls_status* status); + +/* return the current HW + Firmware combination's TDLS capabilities */ +wifi_error wifi_get_tdls_capabilities(wifi_interface_handle iface, + wifi_tdls_capabilities* capabilities); +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h new file mode 100644 index 0000000..5b82b32 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/uevent.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 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 _HARDWARE_UEVENT_H +#define _HARDWARE_UEVENT_H + +#if __cplusplus +extern "C" { +#endif + +int uevent_init(); +int uevent_get_fd(); +int uevent_next_event(char* buffer, int buffer_length); +int uevent_add_native_handler(void (*handler)(void* data, const char* msg, int msg_len), + void* handler_data); +int uevent_remove_native_handler(void (*handler)(void* data, const char* msg, int msg_len)); + +#if __cplusplus +} // extern "C" +#endif + +#endif // _HARDWARE_UEVENT_H diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h new file mode 100644 index 0000000..c7392c2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_cached_scan_results.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 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 __WIFI_CACHED_SCAN_RESULTS_H__ +#define __WIFI_CACHED_SCAN_RESULTS_H__ + +#include "wifi_hal.h" + +#define WIFI_CACHED_SCAN_RESULT_FLAGS_NONE (0) +/* Element ID 61 (HT Operation) is present (see HT 7.3.2) */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_HT_OPS_PRESENT (1 << 0) +/* Element ID 192 (VHT Operation) is present (see VHT 8.4.2) */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_VHT_OPS_PRESENT (1 << 1) +/* Element ID 255 + Extension 36 (HE Operation) is present + * (see 802.11ax 9.4.2.1) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_HE_OPS_PRESENT (1 << 2) +/* Element ID 255 + Extension 106 (HE Operation) is present + * (see 802.11be D1.5 9.4.2.1) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_EHT_OPS_PRESENT (1 << 3) +/* Element ID 127 (Extended Capabilities) is present, and bit 70 + * (Fine Timing Measurement Responder) is set to 1 + * (see IEEE Std 802.11-2016 9.4.2.27) + */ +#define WIFI_CACHED_SCAN_RESULT_FLAGS_IS_FTM_RESPONDER (1 << 4) + +/** + * Provides information about a single access point (AP) detected in a scan. + */ +typedef struct { + /* Number of milliseconds prior to ts in the enclosing + * wifi_cached_scan_result_report struct when + * the probe response or beacon frame that + * was used to populate this structure was received. + */ + u32 age_ms; + /* The Capability Information field */ + u16 capability; + /* null terminated */ + u8 ssid[33]; + u8 ssid_len; + u8 bssid[6]; + /* A set of flags from WIFI_CACHED_SCAN_RESULT_FLAGS_* */ + u8 flags; + s8 rssi; + wifi_channel_spec chanspec; +} wifi_cached_scan_result; + +/* + * Data structure sent with events of type WifiCachedScanResult. + */ +typedef struct { + /* time since boot (in microsecond) when the result was retrieved */ + wifi_timestamp ts; + /* If 0, indicates that all frequencies in current regulation were + * scanned. Otherwise, indicates the number of frequencies scanned, as + * specified in scanned_freq_list. + */ + u16 scanned_freq_num; + /* Pointer to an array containing scanned_freq_num values comprising the + * set of frequencies that were scanned. Frequencies are specified as + * channel center frequencies in MHz. May be NULL if scannedFreqListLen is + * 0. + */ + const u32* scanned_freq_list; + /* The total number of cached results returned. */ + u8 result_cnt; + /* Pointer to an array containing result_cnt entries. May be NULL if + * result_cnt is 0. + */ + const wifi_cached_scan_result* results; +} wifi_cached_scan_report; + +/* callback for reporting cached scan report */ +typedef struct { + void (*on_cached_scan_results)(wifi_cached_scan_report* cache_report); +} wifi_cached_scan_result_handler; +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h new file mode 100644 index 0000000..459a3fe --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_config.h @@ -0,0 +1,44 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_CONFIG_H +#define __WIFI_HAL_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define CONFIG_MAJOR_VERSION 1 +#define CONFIG_MINOR_VERSION 0 +#define CONFIG_MICRO_VERSION 0 + +// whether the wifi chipset wakes at every dtim beacon or a multiple of the dtim period +// if extended_dtim is set to 3, the STA shall wake up every 3 DTIM beacons +wifi_error wifi_extended_dtim_config_set(wifi_request_id id, wifi_interface_handle iface, + int extended_dtim); + +// set the country code to driver +wifi_error wifi_set_country_code(wifi_interface_handle iface, const char* country_code); + +// set the wifi_iface stats averaging factor used to calculate +// statistics like average the TSF offset or average number of frame leaked +// For instance, upon beacon reception: +// current_avg = ((beacon_TSF - TBTT) * factor + previous_avg * (0x10000 - factor) ) / 0x10000 +// For instance, when evaluating leaky APs: +// current_avg = ((num frame received within guard time) * factor + previous_avg * (0x10000 - +// factor)) / 0x10000 + +wifi_error wifi_set_beacon_wifi_iface_stats_averaging_factor(wifi_request_id id, + wifi_interface_handle iface, + u16 factor); + +// configure guard time, i.e. when implementing IEEE power management based on +// frame control PM bit, how long driver waits before shutting down the radio and +// after receiving an ACK for a data frame with PM bit set +wifi_error wifi_set_guard_time(wifi_request_id id, wifi_interface_handle iface, u32 guard_time); + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_STATS_ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h new file mode 100644 index 0000000..383ba71 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_hal.h @@ -0,0 +1,1020 @@ +/* + * 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 __WIFI_HAL_H__ +#define __WIFI_HAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#include + +#define IFNAMSIZ 16 + +/* typedefs */ +typedef unsigned char byte; +typedef unsigned char u8; +typedef signed char s8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint64_t u64; +typedef int64_t s64; +typedef int wifi_request_id; +typedef int wifi_channel; // indicates channel frequency in MHz +typedef int wifi_rssi; +typedef int wifi_radio; +typedef byte mac_addr[6]; +typedef byte oui[3]; +typedef int64_t wifi_timestamp; // In microseconds (us) +typedef int64_t wifi_timespan; // In picoseconds (ps) +typedef uint64_t feature_set; + +/* forward declarations */ +struct wifi_info; +struct wifi_interface_info; +typedef struct wifi_info* wifi_handle; +typedef struct wifi_interface_info* wifi_interface_handle; + +/* WiFi Common definitions */ +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_320 = 7, + WIFI_CHAN_WIDTH_INVALID = -1 +} wifi_channel_width; + +/* Pre selected Power scenarios to be applied from BDF file */ +typedef enum { + WIFI_POWER_SCENARIO_INVALID = -2, + WIFI_POWER_SCENARIO_DEFAULT = -1, + WIFI_POWER_SCENARIO_VOICE_CALL = 0, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF = 1, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON = 2, + WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF = 3, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON = 4, + WIFI_POWER_SCENARIO_ON_BODY_BT = 5, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT = 6, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW = 7, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT = 8, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT = 9, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT = 10, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW = 11, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW = 12, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF_UNFOLDED = 13, + WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON_UNFOLDED = 14, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_UNFOLDED = 15, + WIFI_POWER_SCENARIO_ON_HEAD_HOTSPOT_MMW_UNFOLDED = 16, + WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF_UNFOLDED = 17, + WIFI_POWER_SCENARIO_ON_BODY_BT_UNFOLDED = 18, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_UNFOLDED = 19, + WIFI_POWER_SCENARIO_ON_BODY_CELL_ON_BT_UNFOLDED = 20, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_UNFOLDED = 21, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_UNFOLDED = 22, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_MMW_UNFOLDED = 23, + WIFI_POWER_SCENARIO_ON_BODY_HOTSPOT_BT_MMW_UNFOLDED = 24, +} wifi_power_scenario; + +typedef enum { + WIFI_LATENCY_MODE_NORMAL = 0, + WIFI_LATENCY_MODE_LOW = 1, +} wifi_latency_mode; + +/* Wifi Thermal mitigation modes */ +typedef enum { + WIFI_MITIGATION_NONE = 0, + WIFI_MITIGATION_LIGHT = 1, + WIFI_MITIGATION_MODERATE = 2, + WIFI_MITIGATION_SEVERE = 3, + WIFI_MITIGATION_CRITICAL = 4, + WIFI_MITIGATION_EMERGENCY = 5, +} wifi_thermal_mode; + +/* + * Wifi voice over IP mode + * may add new modes later, for example, voice + video over IP mode. + */ +typedef enum { + WIFI_VOIP_MODE_OFF = 0, + WIFI_VOIP_MODE_ON = 1, +} wifi_voip_mode; + +/* List of interface types supported */ +typedef enum { + WIFI_INTERFACE_TYPE_STA = 0, + WIFI_INTERFACE_TYPE_AP = 1, + WIFI_INTERFACE_TYPE_P2P = 2, + WIFI_INTERFACE_TYPE_NAN = 3, +} wifi_interface_type; + +/* + * enum wlan_mac_band - Band information corresponding to the WLAN MAC. + */ +typedef enum { + /* WLAN MAC Operates in 2.4 GHz Band */ + WLAN_MAC_2_4_BAND = 1 << 0, + /* WLAN MAC Operates in 5 GHz Band */ + WLAN_MAC_5_0_BAND = 1 << 1, + /* WLAN MAC Operates in 6 GHz Band */ + WLAN_MAC_6_0_BAND = 1 << 2, + /* WLAN MAC Operates in 60 GHz Band */ + WLAN_MAC_60_0_BAND = 1 << 3, +} wlan_mac_band; + +/* List of chre nan rtt state */ +typedef enum { + CHRE_PREEMPTED = 0, + CHRE_UNAVAILABLE = 1, + CHRE_AVAILABLE = 2, +} chre_nan_rtt_state; + +typedef struct { + wifi_channel_width width; + int center_frequency0; + int center_frequency1; + int primary_frequency; +} wifi_channel_spec; + +/* + * wifi_usable_channel specifies a channel frequency, bandwidth, and bitmask + * of modes allowed on the channel. + */ +typedef struct { + /* Channel frequency in MHz */ + wifi_channel freq; + /* Channel operating width (20, 40, 80, 160, 320 etc.) */ + wifi_channel_width width; + /* BIT MASK of BIT(WIFI_INTERFACE_*) represented by |wifi_interface_mode| + * Bitmask does not represent concurrency. + * Examples: + * - If a channel is usable only for STA, then only the WIFI_INTERFACE_STA + * bit would be set for that channel. + * - If 5GHz SAP is not allowed, then none of the 5GHz channels will have + * WIFI_INTERFACE_SOFTAP bit set. + * Note: TDLS bit is set only if there is a STA connection. TDLS bit is set + * on non-STA channels only if TDLS off channel is supported. + */ + u32 iface_mode_mask; +} wifi_usable_channel; + +/* + * wifi_usable_channel_filter + */ +typedef enum { + /* Filter Wifi channels that should be avoided due to cellular coex + * restrictions. Some Wifi channels can have extreme interference + * from/to cellular due to short frequency separation with neighboring + * cellular channels or when there is harmonic and intermodulation + * interference. Channels which only have some performance degradation + * (e.g. power back off is sufficient to deal with coexistence issue) + * can be included and should not be filtered out. + */ + WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE = 1 << 0, + /* Filter channels due to concurrency state. + * Examples: + * - 5GHz SAP operation may be supported in standalone mode, but if + * there is STA connection on 5GHz DFS channel, none of the 5GHz + * channels are usable for SAP if device does not support DFS SAP mode. + * - P2P GO may not be supported on indoor channels in EU during + * standalone mode but if there is a STA connection on indoor channel, + * P2P GO may be supported by some vendors on the same STA channel. + */ + WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY = 1 << 1, + /* This Filter queries Wifi channels and bands that are supported for + * NAN3.1 Instant communication mode. This filter should only be applied to NAN interface. + * If 5G is supported default discovery channel 149/44 is considered, + * If 5G is not supported then channel 6 has to be considered. + * Based on regulatory domain if channel 149 and 44 are restricted, channel 6 should + * be considered for instant communication channel + */ + WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE = 1 << 2, +} wifi_usable_channel_filter; + +typedef enum { + WIFI_SUCCESS = 0, + WIFI_ERROR_NONE = 0, + WIFI_ERROR_UNKNOWN = -1, + WIFI_ERROR_UNINITIALIZED = -2, + WIFI_ERROR_NOT_SUPPORTED = -3, + WIFI_ERROR_NOT_AVAILABLE = -4, // Not available right now, but try later + WIFI_ERROR_INVALID_ARGS = -5, + WIFI_ERROR_INVALID_REQUEST_ID = -6, + WIFI_ERROR_TIMED_OUT = -7, + WIFI_ERROR_TOO_MANY_REQUESTS = -8, // Too many instances of this request + WIFI_ERROR_OUT_OF_MEMORY = -9, + WIFI_ERROR_BUSY = -10, +} wifi_error; + +typedef enum { + WIFI_ACCESS_CATEGORY_BEST_EFFORT = 0, + WIFI_ACCESS_CATEGORY_BACKGROUND = 1, + WIFI_ACCESS_CATEGORY_VIDEO = 2, + WIFI_ACCESS_CATEGORY_VOICE = 3 +} wifi_access_category; + +/* Antenna configuration */ +typedef enum { + WIFI_ANTENNA_UNSPECIFIED = 0, + WIFI_ANTENNA_1X1 = 1, + WIFI_ANTENNA_2X2 = 2, + WIFI_ANTENNA_3X3 = 3, + WIFI_ANTENNA_4X4 = 4, +} wifi_antenna_configuration; + +/* Wifi Radio configuration */ +typedef struct { + /* Operating band */ + wlan_mac_band band; + /* Antenna configuration */ + wifi_antenna_configuration antenna_cfg; +} wifi_radio_configuration; + +/* WiFi Radio Combination */ +typedef struct { + u32 num_radio_configurations; + wifi_radio_configuration radio_configurations[]; +} wifi_radio_combination; + +/* WiFi Radio combinations matrix */ +/* For Example in case of a chip which has two radios, where one radio is + * capable of 2.4GHz 2X2 only and another radio which is capable of either + * 5GHz or 6GHz 2X2, number of possible radio combinations in this case + * are 5 and possible combinations are + * {{{2G 2X2}}, //Standalone 2G + * {{5G 2X2}}, //Standalone 5G + * {{6G 2X2}}, //Standalone 6G + * {{2G 2X2}, {5G 2X2}}, //2G+5G DBS + * {{2G 2X2}, {6G 2X2}}} //2G+6G DBS + * Note: Since this chip doesn’t support 5G+6G simultaneous operation + * as there is only one radio which can support both, So it can only + * do MCC 5G+6G. This table should not get populated with possible MCC + * configurations. This is only for simultaneous radio configurations + * (such as Standalone, multi band simultaneous or single band simultaneous). + */ +typedef struct { + u32 num_radio_combinations; + /* Each row represents possible radio combinations */ + wifi_radio_combination radio_combinations[]; +} wifi_radio_combination_matrix; + +/* Initialize/Cleanup */ + +wifi_error wifi_initialize(wifi_handle* handle); + +/** + * wifi_wait_for_driver + * Function should block until the driver is ready to proceed. + * Any errors from this function is considered fatal & will fail the HAL startup sequence. + * + * on success returns WIFI_SUCCESS + * on failure returns WIFI_ERROR_TIMED_OUT + */ +wifi_error wifi_wait_for_driver_ready(void); + +typedef void (*wifi_cleaned_up_handler)(wifi_handle handle); +void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler); +void wifi_event_loop(wifi_handle handle); + +/* Error handling */ +void wifi_get_error_info(wifi_error err, const char** msg); // return a pointer to a static string + +/* Feature enums */ +#define WIFI_FEATURE_INFRA (uint64_t)0x1 // Basic infrastructure mode +#define WIFI_FEATURE_INFRA_5G (uint64_t)0x2 // Support for 5 GHz Band +#define WIFI_FEATURE_HOTSPOT (uint64_t)0x4 // Support for GAS/ANQP +#define WIFI_FEATURE_P2P (uint64_t)0x8 // Wifi-Direct +#define WIFI_FEATURE_SOFT_AP (uint64_t)0x10 // Soft AP +#define WIFI_FEATURE_GSCAN (uint64_t)0x20 // Google-Scan APIs +#define WIFI_FEATURE_NAN (uint64_t)0x40 // Neighbor Awareness Networking +#define WIFI_FEATURE_D2D_RTT (uint64_t)0x80 // Device-to-device RTT +#define WIFI_FEATURE_D2AP_RTT (uint64_t)0x100 // Device-to-AP RTT +#define WIFI_FEATURE_BATCH_SCAN (uint64_t)0x200 // Batched Scan (legacy) +#define WIFI_FEATURE_PNO (uint64_t)0x400 // Preferred network offload +#define WIFI_FEATURE_ADDITIONAL_STA (uint64_t)0x800 // Support for two STAs +#define WIFI_FEATURE_TDLS (uint64_t)0x1000 // Tunnel directed link setup +#define WIFI_FEATURE_TDLS_OFFCHANNEL (uint64_t)0x2000 // Support for TDLS off channel +#define WIFI_FEATURE_EPR (uint64_t)0x4000 // Enhanced power reporting +#define WIFI_FEATURE_AP_STA (uint64_t)0x8000 // Support for AP STA Concurrency +#define WIFI_FEATURE_LINK_LAYER_STATS (uint64_t)0x10000 // Link layer stats collection +#define WIFI_FEATURE_LOGGER (uint64_t)0x20000 // WiFi Logger +#define WIFI_FEATURE_HAL_EPNO (uint64_t)0x40000 // WiFi PNO enhanced +#define WIFI_FEATURE_RSSI_MONITOR (uint64_t)0x80000 // RSSI Monitor +#define WIFI_FEATURE_MKEEP_ALIVE (uint64_t)0x100000 // WiFi mkeep_alive +#define WIFI_FEATURE_CONFIG_NDO (uint64_t)0x200000 // ND offload configure +#define WIFI_FEATURE_TX_TRANSMIT_POWER (uint64_t)0x400000 // Capture Tx transmit power levels +#define WIFI_FEATURE_CONTROL_ROAMING (uint64_t)0x800000 // Enable/Disable firmware roaming +#define WIFI_FEATURE_IE_WHITELIST (uint64_t)0x1000000 // Support Probe IE white listing +#define WIFI_FEATURE_SCAN_RAND \ + (uint64_t)0x2000000 // Support MAC & Probe Sequence Number randomization +#define WIFI_FEATURE_SET_TX_POWER_LIMIT (uint64_t)0x4000000 // Support Tx Power Limit setting +#define WIFI_FEATURE_USE_BODY_HEAD_SAR \ + (uint64_t)0x8000000 // Support Using Body/Head Proximity for SAR +#define WIFI_FEATURE_DYNAMIC_SET_MAC \ + (uint64_t)0x10000000 // Support changing MAC address without iface reset(down and up) +#define WIFI_FEATURE_SET_LATENCY_MODE (uint64_t)0x40000000 // Support Latency mode setting +#define WIFI_FEATURE_P2P_RAND_MAC (uint64_t)0x80000000 // Support P2P MAC randomization +#define WIFI_FEATURE_INFRA_60G (uint64_t)0x100000000 // Support for 60GHz Band +// Add more features here + +#define IS_MASK_SET(mask, flags) (((flags) & (mask)) == (mask)) + +#define IS_SUPPORTED_FEATURE(feature, featureSet) IS_MASK_SET(feature, featureSet) + +/* Feature set */ +wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set* set); + +/* + * Each row represents a valid feature combination; + * all other combinations are invalid! + */ +wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, + feature_set set[], int* set_size); + +/* multiple interface support */ + +wifi_error wifi_get_ifaces(wifi_handle handle, int* num_ifaces, wifi_interface_handle** ifaces); +wifi_error wifi_get_iface_name(wifi_interface_handle iface, char* name, size_t size); +wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char* name); + +/* STA + STA support - Supported if WIFI_FEATURE_ADDITIONAL_STA is set */ + +/** + * Invoked to indicate that the provided iface is the primary STA iface when there are more + * than 1 STA iface concurrently active. + * + * Note: If the wifi firmware/chip cannot support multiple instances of any offload + * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these + * offloads are at least enabled for the primary interface. If the new primary interface is + * already connected to a network, the firmware must switch all the offloads on + * this new interface without disconnecting. + */ +wifi_error wifi_multi_sta_set_primary_connection(wifi_handle handle, wifi_interface_handle iface); + +/** + * When there are 2 or more simultaneous STA connections, this use case hint indicates what + * use-case is being enabled by the framework. This use case hint can be used by the firmware + * to modify various firmware configurations like: + * - Allowed BSSIDs the firmware can choose for the initial connection/roaming attempts. + * - Duty cycle to choose for the 2 STA connections if the radio is in MCC mode. + * - Whether roaming, APF and other offloads needs to be enabled or not. + * + * Note: + * - This will be invoked before an active wifi connection is established on the second interface. + * - This use-case hint is implicitly void when the second STA interface is brought down. + */ +typedef enum { + /** + * Usage: + * - This will be sent down for make before break use-case. + * - Platform is trying to speculatively connect to a second network and evaluate it without + * disrupting the primary connection. + * + * Requirements for Firmware: + * - Do not reduce the number of tx/rx chains of primary connection. + * - If using MCC, should set the MCC duty cycle of the primary connection to be higher than + * the secondary connection (maybe 70/30 split). + * - Should pick the best BSSID for the secondary STA (disregard the chip mode) independent of + * the primary STA: + * - Don’t optimize for DBS vs MCC/SCC + * - Should not impact the primary connection’s bssid selection: + * - Don’t downgrade chains of the existing primary connection. + * - Don’t optimize for DBS vs MCC/SCC. + */ + WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0, + /** + * Usage: + * - This will be sent down for any app requested peer to peer connections. + * - In this case, both the connections needs to be allocated equal resources. + * - For the peer to peer use case, BSSID for the secondary connection will be chosen by the + * framework. + * + * Requirements for Firmware: + * - Can choose MCC or DBS mode depending on the MCC efficiency and HW capability. + * - If using MCC, set the MCC duty cycle of the primary connection to be equal to the secondary + * connection. + * - Prefer BSSID candidates which will help provide the best "overall" performance for both the + * connections. + */ + WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED = 1 +} wifi_multi_sta_use_case; + +wifi_error wifi_multi_sta_set_use_case(wifi_handle handle, wifi_multi_sta_use_case use_case); + +/* Configuration events */ + +typedef struct { + void (*on_country_code_changed)(char code[2]); // We can get this from supplicant too + + // More event handlers +} wifi_event_handler; + +typedef struct { + char iface_name[IFNAMSIZ + 1]; + wifi_channel channel; +} wifi_iface_info; + +typedef struct { + u32 wlan_mac_id; + /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */ + u32 mac_band; + /* Represents the connected Wi-Fi interfaces associated with each MAC */ + int num_iface; + wifi_iface_info* iface_info; +} wifi_mac_info; + +typedef struct { + void (*on_radio_mode_change)(wifi_request_id id, unsigned num_mac, wifi_mac_info* mac_info); +} wifi_radio_mode_change_handler; + +typedef struct { + void (*on_rssi_threshold_breached)(wifi_request_id id, u8* cur_bssid, s8 cur_rssi); +} wifi_rssi_event_handler; + +typedef struct { + void (*on_subsystem_restart)(const char* error); +} wifi_subsystem_restart_handler; + +typedef struct { + void (*on_chre_nan_rtt_change)(chre_nan_rtt_state state); +} wifi_chre_handler; + +wifi_error wifi_set_iface_event_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_event_handler eh); +wifi_error wifi_reset_iface_event_handler(wifi_request_id id, wifi_interface_handle iface); + +wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs); +wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, + wifi_power_scenario scenario); +wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle); +wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode); +wifi_error wifi_map_dscp_access_category(wifi_handle handle, uint32_t start, uint32_t end, + uint32_t access_category); +wifi_error wifi_reset_dscp_mapping(wifi_handle handle); + +wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle, + wifi_subsystem_restart_handler handler); + +/** + * Wifi HAL Thermal Mitigation API + * + * wifi_handle : wifi global handle (note: this is not a interface specific + * command). Mitigation is expected to be applied across all active interfaces + * The implementation and the mitigation action mapping to each mode is chip + * specific. Mitigation will be active until Wifi is turned off or + * WIFI_MITIGATION_NONE mode is sent + * + * mode: Thermal mitigation mode + * WIFI_MITIGATION_NONE : Clear all Wifi thermal mitigation actions + * WIFI_MITIGATION_LIGHT : Light Throttling where UX is not impacted + * WIFI_MITIGATION_MODERATE : Moderate throttling where UX not largely impacted + * WIFI_MITIGATION_SEVERE : Severe throttling where UX is largely impacted + * WIFI_MITIGATION_CRITICAL : Platform has done everything to reduce power + * WIFI_MITIGATION_EMERGENCY: Key components in platform are shutting down + * + * completion_window + * Deadline (in milliseconds) to complete this request, value 0 implies apply + * immediately. Deadline is basically a relaxed limit and allows vendors to + * apply the mitigation within the window (if it cannot apply immediately) + * + * Return + * WIFI_ERROR_NOT_SUPPORTED : Chip does not support thermal mitigation + * WIFI_ERROR_BUSY : Mitigation is supported, but retry later + * WIFI_ERROR_NONE : Mitigation request has been accepted + */ +wifi_error wifi_set_thermal_mitigation_mode(wifi_handle handle, wifi_thermal_mode mode, + u32 completion_window); + +typedef struct rx_data_cnt_details_t { + int rx_unicast_cnt; /*Total rx unicast packet which woke up host */ + int rx_multicast_cnt; /*Total rx multicast packet which woke up host */ + int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */ +} RX_DATA_WAKE_CNT_DETAILS; + +typedef struct rx_wake_pkt_type_classification_t { + int icmp_pkt; /*wake icmp packet count */ + int icmp6_pkt; /*wake icmp6 packet count */ + int icmp6_ra; /*wake icmp6 RA packet count */ + int icmp6_na; /*wake icmp6 NA packet count */ + int icmp6_ns; /*wake icmp6 NS packet count */ + // ToDo: Any more interesting classification to add? +} RX_WAKE_PKT_TYPE_CLASSFICATION; + +typedef struct rx_multicast_cnt_t { + int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */ + int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */ + int other_rx_multicast_addr_cnt; /*Rx wake packet was non-ipv4 and non-ipv6*/ +} RX_MULTICAST_WAKE_DATA_CNT; + +/* + * Structure holding all the driver/firmware wake count reasons. + * + * Buffers for the array fields (cmd_event_wake_cnt/driver_fw_local_wake_cnt) + * are allocated and freed by the framework. The size of each allocated + * array is indicated by the corresponding |_cnt| field. HAL needs to fill in + * the corresponding |_used| field to indicate the number of elements used in + * the array. + */ +typedef struct wlan_driver_wake_reason_cnt_t { + int total_cmd_event_wake; /* Total count of cmd event wakes */ + int* cmd_event_wake_cnt; /* Individual wake count array, each index a reason */ + int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */ + int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */ + + int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */ + int* driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */ + int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */ + int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the + driver */ + + int total_rx_data_wake; /* total data rx packets, that woke up host */ + RX_DATA_WAKE_CNT_DETAILS rx_wake_details; + RX_WAKE_PKT_TYPE_CLASSFICATION rx_wake_pkt_classification_info; + RX_MULTICAST_WAKE_DATA_CNT rx_multicast_wake_pkt_info; +} WLAN_DRIVER_WAKE_REASON_CNT; + +/* Wi-Fi coex channel avoidance support */ + +#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFF + +typedef enum { WIFI_AWARE = 1 << 0, SOFTAP = 1 << 1, WIFI_DIRECT = 1 << 2 } wifi_coex_restriction; + +/** + * Representation of a Wi-Fi channel to be avoided for Wi-Fi coex channel avoidance. + * + * band is represented as an WLAN_MAC* enum value defined in wlan_mac_band. + * If power_cap_dbm is WIFI_COEX_NO_POWER_CAP, then no power cap should be applied if the specified + * channel is used. + */ +typedef struct { + wlan_mac_band band; + u32 channel; + s32 power_cap_dbm; +} wifi_coex_unsafe_channel; + +/* include various feature headers */ + +#include "gscan.h" +#include "link_layer_stats.h" +#include "roam.h" +#include "rtt.h" +#include "tdls.h" +#include "wifi_cached_scan_results.h" +#include "wifi_config.h" +#include "wifi_logger.h" +#include "wifi_nan.h" +#include "wifi_offload.h" +#include "wifi_twt.h" + +// wifi HAL function pointer table +typedef struct { + wifi_error (*wifi_initialize)(wifi_handle*); + wifi_error (*wifi_wait_for_driver_ready)(void); + void (*wifi_cleanup)(wifi_handle, wifi_cleaned_up_handler); + void (*wifi_event_loop)(wifi_handle); + void (*wifi_get_error_info)(wifi_error, const char**); + wifi_error (*wifi_get_supported_feature_set)(wifi_interface_handle, feature_set*); + wifi_error (*wifi_get_concurrency_matrix)(wifi_interface_handle, int, feature_set*, int*); + wifi_error (*wifi_set_scanning_mac_oui)(wifi_interface_handle, unsigned char*); + wifi_error (*wifi_get_supported_channels)(wifi_handle, int*, wifi_channel*); + wifi_error (*wifi_is_epr_supported)(wifi_handle); + wifi_error (*wifi_get_ifaces)(wifi_handle, int*, wifi_interface_handle**); + wifi_error (*wifi_get_iface_name)(wifi_interface_handle, char* name, size_t); + wifi_error (*wifi_set_iface_event_handler)(wifi_request_id, wifi_interface_handle, + wifi_event_handler); + wifi_error (*wifi_reset_iface_event_handler)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_start_gscan)(wifi_request_id, wifi_interface_handle, wifi_scan_cmd_params, + wifi_scan_result_handler); + wifi_error (*wifi_stop_gscan)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_get_cached_gscan_results)(wifi_interface_handle, byte, int, + wifi_cached_scan_results*, int*); + wifi_error (*wifi_set_bssid_hotlist)(wifi_request_id, wifi_interface_handle, + wifi_bssid_hotlist_params, wifi_hotlist_ap_found_handler); + wifi_error (*wifi_reset_bssid_hotlist)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_set_significant_change_handler)(wifi_request_id, wifi_interface_handle, + wifi_significant_change_params, + wifi_significant_change_handler); + wifi_error (*wifi_reset_significant_change_handler)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_get_gscan_capabilities)(wifi_interface_handle, wifi_gscan_capabilities*); + wifi_error (*wifi_set_link_stats)(wifi_interface_handle, wifi_link_layer_params); + wifi_error (*wifi_get_link_stats)(wifi_request_id, wifi_interface_handle, + wifi_stats_result_handler); + wifi_error (*wifi_clear_link_stats)(wifi_interface_handle, u32, u32*, u8, u8*); + wifi_error (*wifi_get_valid_channels)(wifi_interface_handle, int, int, wifi_channel*, int*); + wifi_error (*wifi_rtt_range_request)(wifi_request_id, wifi_interface_handle, unsigned, + wifi_rtt_config[], wifi_rtt_event_handler); + wifi_error (*wifi_rtt_range_cancel)(wifi_request_id, wifi_interface_handle, unsigned, + mac_addr[]); + wifi_error (*wifi_get_rtt_capabilities)(wifi_interface_handle, wifi_rtt_capabilities*); + wifi_error (*wifi_rtt_get_responder_info)(wifi_interface_handle iface, + wifi_rtt_responder* responder_info); + wifi_error (*wifi_enable_responder)(wifi_request_id id, wifi_interface_handle iface, + wifi_channel_info channel_hint, + unsigned max_duration_seconds, + wifi_rtt_responder* responder_info); + wifi_error (*wifi_disable_responder)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_nodfs_flag)(wifi_interface_handle, u32); + wifi_error (*wifi_start_logging)(wifi_interface_handle, u32, u32, u32, u32, char*); + wifi_error (*wifi_set_epno_list)(wifi_request_id, wifi_interface_handle, + const wifi_epno_params*, wifi_epno_handler); + wifi_error (*wifi_reset_epno_list)(wifi_request_id, wifi_interface_handle); + wifi_error (*wifi_set_country_code)(wifi_interface_handle, const char*); + wifi_error (*wifi_get_firmware_memory_dump)(wifi_interface_handle iface, + wifi_firmware_memory_dump_handler handler); + wifi_error (*wifi_set_log_handler)(wifi_request_id id, wifi_interface_handle iface, + wifi_ring_buffer_data_handler handler); + wifi_error (*wifi_reset_log_handler)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_alert_handler)(wifi_request_id id, wifi_interface_handle iface, + wifi_alert_handler handler); + wifi_error (*wifi_reset_alert_handler)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_get_firmware_version)(wifi_interface_handle iface, char* buffer, + int buffer_size); + wifi_error (*wifi_get_ring_buffers_status)(wifi_interface_handle iface, u32* num_rings, + wifi_ring_buffer_status* status); + wifi_error (*wifi_get_logger_supported_feature_set)(wifi_interface_handle iface, + unsigned int* support); + wifi_error (*wifi_get_ring_data)(wifi_interface_handle iface, char* ring_name); + wifi_error (*wifi_enable_tdls)(wifi_interface_handle, mac_addr, wifi_tdls_params*, + wifi_tdls_handler); + wifi_error (*wifi_disable_tdls)(wifi_interface_handle, mac_addr); + wifi_error (*wifi_get_tdls_status)(wifi_interface_handle, mac_addr, wifi_tdls_status*); + wifi_error (*wifi_get_tdls_capabilities)(wifi_interface_handle iface, + wifi_tdls_capabilities* capabilities); + wifi_error (*wifi_get_driver_version)(wifi_interface_handle iface, char* buffer, + int buffer_size); + wifi_error (*wifi_set_passpoint_list)(wifi_request_id id, wifi_interface_handle iface, int num, + wifi_passpoint_network* networks, + wifi_passpoint_event_handler handler); + wifi_error (*wifi_reset_passpoint_list)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_set_lci)(wifi_request_id id, wifi_interface_handle iface, + wifi_lci_information* lci); + wifi_error (*wifi_set_lcr)(wifi_request_id id, wifi_interface_handle iface, + wifi_lcr_information* lcr); + wifi_error (*wifi_start_sending_offloaded_packet)(wifi_request_id id, + wifi_interface_handle iface, u16 ether_type, + u8* ip_packet, u16 ip_packet_len, + u8* src_mac_addr, u8* dst_mac_addr, + u32 period_msec); + wifi_error (*wifi_stop_sending_offloaded_packet)(wifi_request_id id, + wifi_interface_handle iface); + wifi_error (*wifi_start_rssi_monitoring)(wifi_request_id id, wifi_interface_handle iface, + s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh); + wifi_error (*wifi_stop_rssi_monitoring)(wifi_request_id id, wifi_interface_handle iface); + wifi_error (*wifi_get_wake_reason_stats)(wifi_interface_handle iface, + WLAN_DRIVER_WAKE_REASON_CNT* wifi_wake_reason_cnt); + wifi_error (*wifi_configure_nd_offload)(wifi_interface_handle iface, u8 enable); + wifi_error (*wifi_get_driver_memory_dump)(wifi_interface_handle iface, + wifi_driver_memory_dump_callbacks callbacks); + wifi_error (*wifi_start_pkt_fate_monitoring)(wifi_interface_handle iface); + wifi_error (*wifi_get_tx_pkt_fates)(wifi_interface_handle handle, + wifi_tx_report* tx_report_bufs, size_t n_requested_fates, + size_t* n_provided_fates); + wifi_error (*wifi_get_rx_pkt_fates)(wifi_interface_handle handle, + wifi_rx_report* rx_report_bufs, size_t n_requested_fates, + size_t* n_provided_fates); + + /* NAN functions */ + wifi_error (*wifi_nan_enable_request)(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + wifi_error (*wifi_nan_disable_request)(transaction_id id, wifi_interface_handle iface); + wifi_error (*wifi_nan_publish_request)(transaction_id id, wifi_interface_handle iface, + NanPublishRequest* msg); + wifi_error (*wifi_nan_publish_cancel_request)(transaction_id id, wifi_interface_handle iface, + NanPublishCancelRequest* msg); + wifi_error (*wifi_nan_subscribe_request)(transaction_id id, wifi_interface_handle iface, + NanSubscribeRequest* msg); + wifi_error (*wifi_nan_subscribe_cancel_request)(transaction_id id, wifi_interface_handle iface, + NanSubscribeCancelRequest* msg); + wifi_error (*wifi_nan_transmit_followup_request)(transaction_id id, wifi_interface_handle iface, + NanTransmitFollowupRequest* msg); + wifi_error (*wifi_nan_stats_request)(transaction_id id, wifi_interface_handle iface, + NanStatsRequest* msg); + wifi_error (*wifi_nan_config_request)(transaction_id id, wifi_interface_handle iface, + NanConfigRequest* msg); + wifi_error (*wifi_nan_tca_request)(transaction_id id, wifi_interface_handle iface, + NanTCARequest* msg); + wifi_error (*wifi_nan_beacon_sdf_payload_request)(transaction_id id, + wifi_interface_handle iface, + NanBeaconSdfPayloadRequest* msg); + wifi_error (*wifi_nan_register_handler)(wifi_interface_handle iface, + NanCallbackHandler handlers); + wifi_error (*wifi_nan_get_version)(wifi_handle handle, NanVersion* version); + wifi_error (*wifi_nan_get_capabilities)(transaction_id id, wifi_interface_handle iface); + wifi_error (*wifi_nan_data_interface_create)(transaction_id id, wifi_interface_handle iface, + char* iface_name); + wifi_error (*wifi_nan_data_interface_delete)(transaction_id id, wifi_interface_handle iface, + char* iface_name); + wifi_error (*wifi_nan_data_request_initiator)(transaction_id id, wifi_interface_handle iface, + NanDataPathInitiatorRequest* msg); + wifi_error (*wifi_nan_data_indication_response)(transaction_id id, wifi_interface_handle iface, + NanDataPathIndicationResponse* msg); + wifi_error (*wifi_nan_data_end)(transaction_id id, wifi_interface_handle iface, + NanDataPathEndRequest* msg); + wifi_error (*wifi_select_tx_power_scenario)(wifi_interface_handle iface, + wifi_power_scenario scenario); + wifi_error (*wifi_reset_tx_power_scenario)(wifi_interface_handle iface); + + /** + * Returns the chipset's hardware filtering capabilities: + * @param version pointer to version of the packet filter interpreter + *                supported, filled in upon return. 0 indicates no support. + * @param max_len pointer to maximum size of the filter bytecode, filled in + *                upon return. + */ + wifi_error (*wifi_get_packet_filter_capabilities)(wifi_interface_handle handle, u32* version, + u32* max_len); + /** +     * Programs the packet filter. + * @param program pointer to the program byte-code. + * @param len length of the program byte-code. +     */ + wifi_error (*wifi_set_packet_filter)(wifi_interface_handle handle, const u8* program, u32 len); + wifi_error (*wifi_read_packet_filter)(wifi_interface_handle handle, u32 src_offset, + u8* host_dst, u32 length); + wifi_error (*wifi_get_roaming_capabilities)(wifi_interface_handle handle, + wifi_roaming_capabilities* caps); + wifi_error (*wifi_enable_firmware_roaming)(wifi_interface_handle handle, + fw_roaming_state_t state); + wifi_error (*wifi_configure_roaming)(wifi_interface_handle handle, + wifi_roaming_config* roaming_config); + wifi_error (*wifi_set_radio_mode_change_handler)(wifi_request_id id, + wifi_interface_handle iface, + wifi_radio_mode_change_handler eh); + wifi_error (*wifi_set_latency_mode)(wifi_interface_handle iface, wifi_latency_mode mode); + wifi_error (*wifi_set_thermal_mitigation_mode)(wifi_handle handle, wifi_thermal_mode mode, + u32 completion_window); + wifi_error (*wifi_map_dscp_access_category)(wifi_handle handle, u32 start, u32 end, + u32 access_category); + wifi_error (*wifi_reset_dscp_mapping)(wifi_handle handle); + + wifi_error (*wifi_virtual_interface_create)(wifi_handle handle, const char* ifname, + wifi_interface_type iface_type); + wifi_error (*wifi_virtual_interface_delete)(wifi_handle handle, const char* ifname); + + wifi_error (*wifi_set_subsystem_restart_handler)(wifi_handle handle, + wifi_subsystem_restart_handler handler); + + /** + * Allow vendor HAL to choose interface name when creating + * an interface. This can be implemented by chips with their + * own interface naming policy. + * If not implemented, the default naming will be used. + */ + wifi_error (*wifi_get_supported_iface_name)(wifi_handle handle, u32 iface_type, char* name, + size_t len); + + /** + * Perform early initialization steps that are needed when WIFI + * is disabled. + * If the function returns failure, it means the vendor HAL is unusable + * (for example, if chip hardware is not installed) and no further + * functions should be called. + */ + wifi_error (*wifi_early_initialize)(void); + + /** + * Get supported feature set which are chip-global, that is + * not dependent on any created interface. + */ + wifi_error (*wifi_get_chip_feature_set)(wifi_handle handle, feature_set* set); + + /** + * Invoked to indicate that the provided iface is the primary STA iface when there are more + * than 1 STA iface concurrently active. + */ + wifi_error (*wifi_multi_sta_set_primary_connection)(wifi_handle handle, + wifi_interface_handle iface); + + /** + * When there are 2 simultaneous STA connections, this use case hint + * indicates what STA + STA use-case is being enabled by the framework. + */ + wifi_error (*wifi_multi_sta_set_use_case)(wifi_handle handle, wifi_multi_sta_use_case use_case); + + /** + * Invoked to indicate that the following list of wifi_coex_unsafe_channel should be avoided + * with the specified restrictions. + * @param unsafeChannels list of current |wifi_coex_unsafe_channel| to avoid. + * @param restrictions bitmask of |wifi_coex_restriction| indicating wifi interfaces to + * restrict from the current unsafe channels. + */ + wifi_error (*wifi_set_coex_unsafe_channels)(wifi_handle handle, u32 num_channels, + wifi_coex_unsafe_channel* unsafeChannels, + u32 restrictions); + + /** + * Invoked to set voip optimization mode for the provided STA iface + */ + wifi_error (*wifi_set_voip_mode)(wifi_interface_handle iface, wifi_voip_mode mode); + + /**@brief twt_register_handler + * Request to register TWT callback before sending any TWT request + * @param wifi_interface_handle: + * @param TwtCallbackHandler: callback function pointers + * @return Synchronous wifi_error + */ + wifi_error (*wifi_twt_register_handler)(wifi_interface_handle iface, + TwtCallbackHandler handler); + + /**@brief twt_get_capability + * Request TWT capability + * @param wifi_interface_handle: + * @return Synchronous wifi_error and TwtCapabilitySet + */ + wifi_error (*wifi_twt_get_capability)(wifi_interface_handle iface, + TwtCapabilitySet* twt_cap_set); + + /**@brief twt_setup_request + * Request to send TWT setup frame + * @param wifi_interface_handle: + * @param TwtSetupRequest: detailed parameters of setup request + * @return Synchronous wifi_error + * @return Asynchronous EventTwtSetupResponse CB return TwtSetupResponse + */ + wifi_error (*wifi_twt_setup_request)(wifi_interface_handle iface, TwtSetupRequest* msg); + + /**@brief twt_teardown_request + * Request to send TWT teardown frame + * @param wifi_interface_handle: + * @param TwtTeardownRequest: detailed parameters of teardown request + * @return Synchronous wifi_error + * @return Asynchronous EventTwtTeardownCompletion CB return TwtTeardownCompletion + * TwtTeardownCompletion may also be received due to other events + * like CSA, BTCX, TWT scheduler, MultiConnection, peer-initiated teardown, etc. + */ + wifi_error (*wifi_twt_teardown_request)(wifi_interface_handle iface, TwtTeardownRequest* msg); + + /**@brief twt_info_frame_request + * Request to send TWT info frame + * @param wifi_interface_handle: + * @param TwtInfoFrameRequest: detailed parameters in info frame + * @return Synchronous wifi_error + * @return Asynchronous EventTwtInfoFrameReceived CB return TwtInfoFrameReceived + * Driver may also receive Peer-initiated TwtInfoFrame + */ + wifi_error (*wifi_twt_info_frame_request)(wifi_interface_handle iface, + TwtInfoFrameRequest* msg); + + /**@brief twt_get_stats + * Request to get TWT stats + * @param wifi_interface_handle: + * @param config_id: configuration ID of TWT request + * @return Synchronous wifi_error and TwtStats + */ + wifi_error (*wifi_twt_get_stats)(wifi_interface_handle iface, u8 config_id, TwtStats* stats); + + /**@brief twt_clear_stats + * Request to clear TWT stats + * @param wifi_interface_handle: + * @param config_id: configuration ID of TWT request + * @return Synchronous wifi_error + */ + wifi_error (*wifi_twt_clear_stats)(wifi_interface_handle iface, u8 config_id); + + /** + * Invoked to set DTIM configuration when the host is in the suspend mode + * @param wifi_interface_handle: + * @param multiplier: when STA in the power saving mode, the wake up interval will be set to + * 1) multiplier * DTIM period if multiplier > 0. + * 2) the device default value if multiplier <=0 + * Some implementations may apply an additional cap to wake up interval in the case of 1). + */ + wifi_error (*wifi_set_dtim_config)(wifi_interface_handle handle, u32 multiplier); + + /**@brief wifi_get_usable_channels + * Request list of usable channels for the requested bands and modes. Usable + * implies channel is allowed as per regulatory for the current country code + * and not restricted due to other hard limitations (e.g. DFS, Coex) In + * certain modes (e.g. STA+SAP) there could be other hard restrictions + * since MCC operation many not be supported by SAP. This API also allows + * driver to return list of usable channels for each mode uniquely to + * distinguish cases where only a limited set of modes are allowed on + * a given channel e.g. srd channels may be supported for P2P but not + * for SAP or P2P-Client may be allowed on an indoor channel but P2P-GO + * may not be allowed. This API is not interface specific and will be + * used to query capabilities of driver in terms of what modes (STA, SAP, + * P2P_CLI, P2P_GO, NAN, TDLS) can be supported on each of the channels. + * @param handle global wifi_handle + * @param band_mask BIT MASK of WLAN_MAC* as represented by |wlan_mac_band| + * @param iface_mode_mask BIT MASK of BIT(WIFI_INTERFACE_*) represented by + * |wifi_interface_mode|. Bitmask respresents all the modes that the + * caller is interested in (e.g. STA, SAP, WFD-CLI, WFD-GO, TDLS, NAN). + * Note: Bitmask does not represent concurrency matrix. If the caller + * is interested in CLI, GO modes, the iface_mode_mask would be set + * to WIFI_INTERFACE_P2P_CLIENT|WIFI_INTERFACE_P2P_GO. + * @param filter_mask BIT MASK of WIFI_USABLE_CHANNEL_FILTER_* represented by + * |wifi_usable_channel_filter|. Indicates if the channel list should + * be filtered based on additional criteria. If filter_mask is not + * specified, driver should return list of usable channels purely + * based on regulatory constraints. + * @param max_size maximum number of |wifi_usable_channel| + * @param size actual number of |wifi_usable_channel| entries returned by driver + * @param channels list of usable channels represented by |wifi_usable_channel| + */ + wifi_error (*wifi_get_usable_channels)(wifi_handle handle, u32 band_mask, u32 iface_mode_mask, + u32 filter_mask, u32 max_size, u32* size, + wifi_usable_channel* channels); + + /** + * Trigger wifi subsystem restart to reload firmware + */ + wifi_error (*wifi_trigger_subsystem_restart)(wifi_handle handle); + + /** + * Invoked to set that the device is operating in an indoor environment. + * @param handle global wifi_handle + * @param isIndoor: true if the device is operating in an indoor + * environment, false otherwise. + * @return Synchronous wifi_error + */ + wifi_error (*wifi_set_indoor_state)(wifi_handle handle, bool isIndoor); + + /**@brief wifi_get_supported_radio_combinations_matrix + * Request all the possible radio combinations this device can offer. + * @param handle global wifi_handle + * @param max_size maximum size allocated for filling the wifi_radio_combination_matrix + * @param wifi_radio_combination_matrix to return all the possible radio + * combinations. + * @param size actual size of wifi_radio_combination_matrix returned from + * lower layer + * + */ + wifi_error (*wifi_get_supported_radio_combinations_matrix)( + wifi_handle handle, u32 max_size, u32* size, + wifi_radio_combination_matrix* radio_combination_matrix); + + /**@brief wifi_nan_rtt_chre_enable_request + * Request to enable CHRE NAN RTT + * @param transaction_id: NAN transaction id + * @param wifi_interface_handle + * @param NanEnableRequest request message + * @return Synchronous wifi_error + */ + wifi_error (*wifi_nan_rtt_chre_enable_request)(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + + /**@brief wifi_nan_rtt_chre_disable_request + * Request to disable CHRE NAN RTT + * @param transaction_id: NAN transaction id + * @param wifi_interface_handle + * @return Synchronous wifi_error + */ + wifi_error (*wifi_nan_rtt_chre_disable_request)(transaction_id id, wifi_interface_handle iface); + + /**@brief wifi_chre_register_handler + * register a handler to get the state of CHR + * @param wifi_interface_handle + * @param wifi_chre_handler: callback function pointer + * @return Synchronous wifi_error + */ + wifi_error (*wifi_chre_register_handler)(wifi_interface_handle iface, + wifi_chre_handler handler); + + /**@brief wifi_enable_tx_power_limits + * Enable WiFi Tx power limis + * @param wifi_interface_handle + * @param isEnable : If enable TX limit or not + * @return Synchronous wifi_error + */ + wifi_error (*wifi_enable_tx_power_limits)(wifi_interface_handle iface, bool isEnable); + + /**@brief wifi_get_cached_scan_results + * Retrieve scan results cached in wifi firmware + * @param wifi_interface_handle + * @param wifi_cached_scan_result_handler : callback function pointer + * @return Synchronous wifi_error + */ + wifi_error (*wifi_get_cached_scan_results)(wifi_interface_handle iface, + wifi_cached_scan_result_handler handler); + /* + * when adding new functions make sure to add stubs in + * hal_tool.cpp::init_wifi_stub_hal_func_table + */ +} wifi_hal_fn; + +wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn* fn); +typedef wifi_error (*init_wifi_vendor_hal_func_table_t)(wifi_hal_fn* fn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h new file mode 100644 index 0000000..76d6f74 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_logger.h @@ -0,0 +1,650 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_LOGGER_H +#define __WIFI_HAL_LOGGER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define LOGGER_MAJOR_VERSION 1 +#define LOGGER_MINOR_VERSION 0 +#define LOGGER_MICRO_VERSION 0 + +/** + * WiFi logger life cycle is as follow: + * + * - At initialization time, framework will call wifi_get_ring_buffers_status + * so as to obtain the names and list of supported buffers. + * - When WiFi operation start framework will call wifi_start_logging + * so as to trigger log collection. + * - Developper UI will provide an option to the user, so as it can set the verbose level + * of individual buffer as reported by wifi_get_ring_buffers_status. + * - During wifi operations, driver will periodically report per ring data to framework + * by invoking the on_ring_buffer_data call back. + * - when capturing a bug report, framework will indicate to driver that all the data + * has to be uploaded, urgently, by calling wifi_get_ring_data. + * + * The data uploaded by driver will be stored by framework in separate files, with one stream + * of file per ring. + * Framework will store the files in pcapng format, allowing for easy merging and parsing + * with network analyzer tools. + */ + +typedef int wifi_ring_buffer_id; + +#define PER_PACKET_ENTRY_FLAGS_DIRECTION_TX 1 // 0: TX, 1: RX +#define PER_PACKET_ENTRY_FLAGS_TX_SUCCESS \ + 2 // whether packet was transmitted or + // received/decrypted successfully +#define PER_PACKET_ENTRY_FLAGS_80211_HEADER 4 // has full 802.11 header, else has 802.3 header +#define PER_PACKET_ENTRY_FLAGS_PROTECTED 8 // whether packet was encrypted + +typedef struct { + u8 flags; + u8 tid; // transmit or received tid + u16 MCS; // modulation and bandwidth + u8 rssi; // TX: RSSI of ACK for that packet + // RX: RSSI of packet + u8 num_retries; // number of attempted retries + u16 last_transmit_rate; // last transmit rate in .5 mbps + u16 link_layer_transmit_sequence; // transmit/reeive sequence for that MPDU packet + u64 firmware_entry_timestamp; // TX: firmware timestamp (us) when packet is queued within + // firmware buffer for SDIO/HSIC or into PCIe buffer + // RX: firmware receive timestamp + u64 start_contention_timestamp; // firmware timestamp (us) when packet start contending for the + // medium for the first time, at head of its AC queue, + // or as part of an MPDU or A-MPDU. This timestamp is + // not updated for each retry, only the first transmit attempt. + u64 transmit_success_timestamp; // fimrware timestamp (us) when packet is successfully + // transmitted or aborted because it has exhausted + // its maximum number of retries. + u8 data[0]; // packet data. The length of packet data is determined by the entry_size field of + // the wifi_ring_buffer_entry structure. It is expected that first bytes of the + // packet, or packet headers only (up to TCP or RTP/UDP headers) + // will be copied into the ring +} __attribute__((packed)) wifi_ring_per_packet_status_entry; + +/* Below events refer to the wifi_connectivity_event ring and shall be supported */ +#define WIFI_EVENT_ASSOCIATION_REQUESTED 0 // driver receives association command from kernel +#define WIFI_EVENT_AUTH_COMPLETE 1 +#define WIFI_EVENT_ASSOC_COMPLETE 2 +#define WIFI_EVENT_FW_AUTH_STARTED 3 // fw event indicating auth frames are sent +#define WIFI_EVENT_FW_ASSOC_STARTED 4 // fw event indicating assoc frames are sent +#define WIFI_EVENT_FW_RE_ASSOC_STARTED 5 // fw event indicating reassoc frames are sent +#define WIFI_EVENT_DRIVER_SCAN_REQUESTED 6 +#define WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND 7 +#define WIFI_EVENT_DRIVER_SCAN_COMPLETE 8 +#define WIFI_EVENT_G_SCAN_STARTED 9 +#define WIFI_EVENT_G_SCAN_COMPLETE 10 +#define WIFI_EVENT_DISASSOCIATION_REQUESTED 11 +#define WIFI_EVENT_RE_ASSOCIATION_REQUESTED 12 +#define WIFI_EVENT_ROAM_REQUESTED 13 +#define WIFI_EVENT_BEACON_RECEIVED \ + 14 // received beacon from AP (event enabled + // only in verbose mode) +#define WIFI_EVENT_ROAM_SCAN_STARTED 15 // firmware has triggered a roam scan (not g-scan) +#define WIFI_EVENT_ROAM_SCAN_COMPLETE 16 // firmware has completed a roam scan (not g-scan) +#define WIFI_EVENT_ROAM_SEARCH_STARTED \ + 17 // firmware has started searching for roam + // candidates (with reason =xx) +#define WIFI_EVENT_ROAM_SEARCH_STOPPED \ + 18 // firmware has stopped searching for roam + // candidates (with reason =xx) +#define WIFI_EVENT_CHANNEL_SWITCH_ANOUNCEMENT 20 // received channel switch anouncement from AP +#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_START \ + 21 // fw start transmit eapol frame, with + // EAPOL index 1-4 +#define WIFI_EVENT_FW_EAPOL_FRAME_TRANSMIT_STOP \ + 22 // fw gives up eapol frame, with rate, + // success/failure and number retries +#define WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED \ + 23 // kernel queue EAPOL for transmission + // in driver with EAPOL index 1-4 +#define WIFI_EVENT_FW_EAPOL_FRAME_RECEIVED \ + 24 // with rate, regardless of the fact that + // EAPOL frame is accepted or rejected by fw +#define WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED \ + 26 // with rate, and eapol index, driver has + // received EAPOL frame and will queue it up + // to wpa_supplicant +#define WIFI_EVENT_BLOCK_ACK_NEGOTIATION_COMPLETE 27 // with success/failure, parameters +#define WIFI_EVENT_BT_COEX_BT_SCO_START 28 +#define WIFI_EVENT_BT_COEX_BT_SCO_STOP 29 +#define WIFI_EVENT_BT_COEX_BT_SCAN_START \ + 30 // for paging/scan etc., when BT starts transmiting + // twice per BT slot +#define WIFI_EVENT_BT_COEX_BT_SCAN_STOP 31 +#define WIFI_EVENT_BT_COEX_BT_HID_START 32 +#define WIFI_EVENT_BT_COEX_BT_HID_STOP 33 +#define WIFI_EVENT_ROAM_AUTH_STARTED 34 // fw sends auth frame in roaming to next candidate +#define WIFI_EVENT_ROAM_AUTH_COMPLETE 35 // fw receive auth confirm from ap +#define WIFI_EVENT_ROAM_ASSOC_STARTED \ + 36 // firmware sends assoc/reassoc frame in + // roaming to next candidate +#define WIFI_EVENT_ROAM_ASSOC_COMPLETE 37 // firmware receive assoc/reassoc confirm from ap +#define WIFI_EVENT_G_SCAN_STOP 38 // firmware sends stop G_SCAN +#define WIFI_EVENT_G_SCAN_CYCLE_STARTED 39 // firmware indicates G_SCAN scan cycle started +#define WIFI_EVENT_G_SCAN_CYCLE_COMPLETED 40 // firmware indicates G_SCAN scan cycle completed +#define WIFI_EVENT_G_SCAN_BUCKET_STARTED \ + 41 // firmware indicates G_SCAN scan start + // for a particular bucket +#define WIFI_EVENT_G_SCAN_BUCKET_COMPLETED \ + 42 // firmware indicates G_SCAN scan completed for + // for a particular bucket +#define WIFI_EVENT_G_SCAN_RESULTS_AVAILABLE \ + 43 // Event received from firmware about G_SCAN scan + // results being available +#define WIFI_EVENT_G_SCAN_CAPABILITIES \ + 44 // Event received from firmware with G_SCAN + // capabilities +#define WIFI_EVENT_ROAM_CANDIDATE_FOUND \ + 45 // Event received from firmware when eligible + // candidate is found +#define WIFI_EVENT_ROAM_SCAN_CONFIG \ + 46 // Event received from firmware when roam scan + // configuration gets enabled or disabled +#define WIFI_EVENT_AUTH_TIMEOUT 47 // firmware/driver timed out authentication +#define WIFI_EVENT_ASSOC_TIMEOUT 48 // firmware/driver timed out association +#define WIFI_EVENT_MEM_ALLOC_FAILURE 49 // firmware/driver encountered allocation failure +#define WIFI_EVENT_DRIVER_PNO_ADD 50 // driver added a PNO network in firmware +#define WIFI_EVENT_DRIVER_PNO_REMOVE 51 // driver removed a PNO network in firmware +#define WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND \ + 52 // driver received PNO networks + // found indication from firmware +#define WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED 53 // driver triggered a scan for PNO networks +#define WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND \ + 54 // driver received scan results + // of PNO networks +#define WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE \ + 55 // driver updated scan results from + // PNO networks to cfg80211 + +/** + * Parameters of wifi logger events are TLVs + * Event parameters tags are defined as: + */ +#define WIFI_TAG_VENDOR_SPECIFIC 0 // take a byte stream as parameter +#define WIFI_TAG_BSSID 1 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR 2 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_SSID 3 // takes a 32 bytes SSID address as parameter +#define WIFI_TAG_STATUS 4 // takes an integer as parameter +#define WIFI_TAG_CHANNEL_SPEC 5 // takes one or more wifi_channel_spec as parameter +#define WIFI_TAG_WAKE_LOCK_EVENT 6 // takes a wake_lock_event struct as parameter +#define WIFI_TAG_ADDR1 7 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR2 8 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR3 9 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_ADDR4 10 // takes a 6 bytes MAC address as parameter +#define WIFI_TAG_TSF 11 // take a 64 bits TSF value as parameter +#define WIFI_TAG_IE \ + 12 // take one or more specific 802.11 IEs parameter, + // IEs are in turn indicated in TLV format as per + // 802.11 spec +#define WIFI_TAG_INTERFACE 13 // take interface name as parameter +#define WIFI_TAG_REASON_CODE 14 // take a reason code as per 802.11 as parameter +#define WIFI_TAG_RATE_MBPS 15 // take a wifi rate in 0.5 mbps +#define WIFI_TAG_REQUEST_ID 16 // take an integer as parameter +#define WIFI_TAG_BUCKET_ID 17 // take an integer as parameter +#define WIFI_TAG_GSCAN_PARAMS 18 // takes a wifi_scan_cmd_params struct as parameter +#define WIFI_TAG_GSCAN_CAPABILITIES 19 // takes a wifi_gscan_capabilities struct as parameter +#define WIFI_TAG_SCAN_ID 20 // take an integer as parameter +#define WIFI_TAG_RSSI 21 // take an integer as parameter +#define WIFI_TAG_CHANNEL 22 // take an integer as parameter +#define WIFI_TAG_LINK_ID 23 // take an integer as parameter +#define WIFI_TAG_LINK_ROLE 24 // take an integer as parameter +#define WIFI_TAG_LINK_STATE 25 // take an integer as parameter +#define WIFI_TAG_LINK_TYPE 26 // take an integer as parameter +#define WIFI_TAG_TSCO 27 // take an integer as parameter +#define WIFI_TAG_RSCO 28 // take an integer as parameter +#define WIFI_TAG_EAPOL_MESSAGE_TYPE \ + 29 // take an integer as parameter + // M1-1, M2-2, M3-3, M4-4 + +typedef struct { + u16 tag; + u16 length; // length of value + u8 value[0]; +} __attribute__((packed)) tlv_log; + +typedef struct { + u16 event; + tlv_log tlvs[0]; // separate parameter structure per event to be provided and optional data + // the event_data is expected to include an official android part, with some + // parameter as transmit rate, num retries, num scan result found etc... + // as well, event_data can include a vendor proprietary part which is + // understood by the developer only. +} __attribute__((packed)) wifi_ring_buffer_driver_connectivity_event; + +/** + * Ring buffer name for power events ring. note that power event are extremely frequents + * and thus should be stored in their own ring/file so as not to clobber connectivity events. + */ +typedef struct { + int status; // 0 taken, 1 released + int reason; // reason why this wake lock is taken + char name[0]; // null terminated +} __attribute__((packed)) wake_lock_event; + +typedef struct { + u16 event; + tlv_log tlvs[0]; +} __attribute__((packed)) wifi_power_event; + +/** + * This structure represent a logger entry within a ring buffer. + * Wifi driver are responsible to manage the ring buffer and write the debug + * information into those rings. + * + * In general, the debug entries can be used to store meaningful 802.11 information (SME, MLME, + * connection and packet statistics) as well as vendor proprietary data that is specific to a + * specific driver or chipset. + * Binary entries can be used so as to store packet data or vendor specific information and + * will be treated as blobs of data by android. + * + * A user land process will be started by framework so as to periodically retrieve the + * data logged by drivers into their ring buffer, store the data into log files and include + * the logs into android bugreports. + */ +enum { + RING_BUFFER_ENTRY_FLAGS_HAS_BINARY = (1 << (0)), // set for binary entries + RING_BUFFER_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1)) // set if 64 bits timestamp is present +}; + +enum { + ENTRY_TYPE_CONNECT_EVENT = 1, + ENTRY_TYPE_PKT, + ENTRY_TYPE_WAKE_LOCK, + ENTRY_TYPE_POWER_EVENT, + ENTRY_TYPE_DATA +}; + +typedef struct { + u16 entry_size; // the size of payload excluding the header. + u8 flags; + u8 type; // entry type + u64 timestamp; // present if has_timestamp bit is set. +} __attribute__((packed)) wifi_ring_buffer_entry; + +#define WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES 0x00000001 // set if binary entries are present +#define WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES 0x00000002 // set if ascii entries are present + +/* ring buffer params */ +/** + * written_bytes and read_bytes implement a producer consumer API + * hence written_bytes >= read_bytes + * a modulo arithmetic of the buffer size has to be applied to those counters: + * actual offset into ring buffer = written_bytes % ring_buffer_byte_size + * + */ +typedef struct { + u8 name[32]; + u32 flags; + wifi_ring_buffer_id ring_id; // unique integer representing the ring + u32 ring_buffer_byte_size; // total memory size allocated for the buffer + u32 verbose_level; // verbose level for ring buffer + u32 written_bytes; // number of bytes that was written to the buffer by driver, + // monotonously increasing integer + u32 read_bytes; // number of bytes that was read from the buffer by user land, + // monotonously increasing integer + u32 written_records; // number of records that was written to the buffer by driver, + // monotonously increasing integer +} wifi_ring_buffer_status; + +/** + * Callback for reporting ring data + * + * The ring buffer data collection is event based: + * - Driver calls on_ring_buffer_data when new records are available, the wifi_ring_buffer_status + * passed up to framework in the call back indicates to framework if more data is available in + * the ring buffer. It is not expected that driver will necessarily always empty the ring + * immediately as data is available, instead driver will report data every X seconds or if + * N bytes are available. + * - In the case where a bug report has to be captured, framework will require driver to upload + * all data immediately. This is indicated to driver when framework calls wifi_get_ringdata. + * When framework calls wifi_get_ring_data, driver will start sending all available data in the + * indicated ring by repeatedly invoking the on_ring_buffer_data callback. + * + * The callback is called by log handler whenever ring data comes in driver. + */ +typedef struct { + void (*on_ring_buffer_data)(char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status); +} wifi_ring_buffer_data_handler; + +/** + * API to set the log handler for getting ring data + * - Only a single instance of log handler can be instantiated for each ring buffer. + */ +wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_ring_buffer_data_handler handler); + +/* API to reset the log handler */ +wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface); + +/** + * Callback for reporting FW dump + * + * The buffer data collection is event based such as FW health check or FW dump. + * The callback is called by alert handler. + */ +typedef struct { + void (*on_alert)(wifi_request_id id, char* buffer, int buffer_size, int err_code); +} wifi_alert_handler; + +/* + * API to set the alert handler for the alert case in Wi-Fi Chip + * - Only a single instance of alert handler can be instantiated. + */ +wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface, + wifi_alert_handler handler); + +/* API to reset the alert handler */ +wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface); + +/* API for framework to indicate driver has to upload and drain all data of a given ring */ +wifi_error wifi_get_ring_data(wifi_interface_handle iface, char* ring_name); + +/** + * API to trigger the debug collection. + * Unless his API is invoked - logging is not triggered. + * - Verbose_level 0 corresponds to no collection, + * and it makes log handler stop by no more events from driver. + * - Verbose_level 1 correspond to normal log level, with minimal user impact. + * This is the default value. + * - Verbose_level 2 are enabled when user is lazily trying to reproduce a problem, + * wifi performances and power can be impacted but device should not otherwise be + * significantly impacted. + * - Verbose_level 3+ are used when trying to actively debug a problem. + * + * ring_name represent the name of the ring for which data collection shall start. + * + * flags: TBD parameter used to enable/disable specific events on a ring + * max_interval: maximum interval in seconds for driver to invoke on_ring_buffer_data, + * ignore if zero + * min_data_size: minimum data size in buffer for driver to invoke on_ring_buffer_data, + * ignore if zero + */ +wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level, u32 flags, + u32 max_interval_sec, u32 min_data_size, char* ring_name); + +/** + * API to get the status of all ring buffers supported by driver. + * - Caller is responsible to allocate / free ring buffer status. + * - Maximum no of ring buffer would be 10. + */ +wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface, u32* num_rings, + wifi_ring_buffer_status* status); + +/** + * Synchronous memory dump by user request. + * - Caller is responsible to store memory dump data into a local, + * e.g., /data/misc/wifi/memdump.bin + */ +typedef struct { + void (*on_firmware_memory_dump)(char* buffer, int buffer_size); +} wifi_firmware_memory_dump_handler; + +/** + * API to collect a firmware memory dump for a given iface by async memdump event. + * - Triggered by Alerthandler, esp. when FW problem or FW health check happens + * - Caller is responsible to store fw dump data into a local, + * e.g., /data/misc/wifi/alertdump-1.bin + */ +wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface, + wifi_firmware_memory_dump_handler handler); + +/** + * API to collect a firmware version string. + * - Caller is responsible to allocate / free a buffer to retrieve firmware verion info. + * - Max string will be at most 256 bytes. + */ +wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char* buffer, int buffer_size); + +/** + * API to collect a driver version string. + * - Caller is responsible to allocate / free a buffer to retrieve driver verion info. + * - Max string will be at most 256 bytes. + */ +wifi_error wifi_get_driver_version(wifi_interface_handle iface, char* buffer, int buffer_size); + +/* Feature set */ +enum { + WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW + WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status + WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event + WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver + WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver + WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW + WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW + WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state + WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate +}; + +/** + * API to retrieve the current supportive features. + * - An integer variable is enough to have bit mapping info by caller. + */ +wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface, + unsigned int* support); + +typedef struct { + /* Buffer is to be allocated and freed by HAL implementation. */ + void (*on_driver_memory_dump)(char* buffer, int buffer_size); +} wifi_driver_memory_dump_callbacks; + +/** + API to collect driver state. + + Framework will call this API soon before or after (but not + concurrently with) wifi_get_firmware_memory_dump(). Capturing + firmware and driver dumps is intended to help identify + inconsistent state between these components. + + - In response to this call, HAL implementation should make one or + more calls to callbacks.on_driver_memory_dump(). Framework will + copy data out of the received |buffer|s, and concatenate the + contents thereof. + - HAL implemention will indicate completion of the driver memory + dump by returning from this call. +*/ +wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface, + wifi_driver_memory_dump_callbacks callbacks); + +/* packet fate logs */ + +#define MD5_PREFIX_LEN 4 +#define MAX_FATE_LOG_LEN 32 +#define MAX_FRAME_LEN_ETHERNET 1518 +#define MAX_FRAME_LEN_80211_MGMT 2352 // 802.11-2012 Fig. 8-34 + +typedef enum { + // Sent over air and ACKed. + TX_PKT_FATE_ACKED, + + // Sent over air but not ACKed. (Normal for broadcast/multicast.) + TX_PKT_FATE_SENT, + + // Queued within firmware, but not yet sent over air. + TX_PKT_FATE_FW_QUEUED, + + // Dropped by firmware as invalid. E.g. bad source address, bad checksum, + // or invalid for current state. + TX_PKT_FATE_FW_DROP_INVALID, + + // Dropped by firmware due to lack of buffer space. + TX_PKT_FATE_FW_DROP_NOBUFS, + + // Dropped by firmware for any other reason. Includes frames that + // were sent by driver to firmware, but unaccounted for by + // firmware. + TX_PKT_FATE_FW_DROP_OTHER, + + // Queued within driver, not yet sent to firmware. + TX_PKT_FATE_DRV_QUEUED, + + // Dropped by driver as invalid. E.g. bad source address, or + // invalid for current state. + TX_PKT_FATE_DRV_DROP_INVALID, + + // Dropped by driver due to lack of buffer space. + TX_PKT_FATE_DRV_DROP_NOBUFS, + + // Dropped by driver for any other reason. + TX_PKT_FATE_DRV_DROP_OTHER, +} wifi_tx_packet_fate; + +typedef enum { + // Valid and delivered to network stack (e.g., netif_rx()). + RX_PKT_FATE_SUCCESS, + + // Queued within firmware, but not yet sent to driver. + RX_PKT_FATE_FW_QUEUED, + + // Dropped by firmware due to host-programmable filters. + RX_PKT_FATE_FW_DROP_FILTER, + + // Dropped by firmware as invalid. E.g. bad checksum, decrypt failed, + // or invalid for current state. + RX_PKT_FATE_FW_DROP_INVALID, + + // Dropped by firmware due to lack of buffer space. + RX_PKT_FATE_FW_DROP_NOBUFS, + + // Dropped by firmware for any other reason. + RX_PKT_FATE_FW_DROP_OTHER, + + // Queued within driver, not yet delivered to network stack. + RX_PKT_FATE_DRV_QUEUED, + + // Dropped by driver due to filter rules. + RX_PKT_FATE_DRV_DROP_FILTER, + + // Dropped by driver as invalid. E.g. not permitted in current state. + RX_PKT_FATE_DRV_DROP_INVALID, + + // Dropped by driver due to lack of buffer space. + RX_PKT_FATE_DRV_DROP_NOBUFS, + + // Dropped by driver for any other reason. + RX_PKT_FATE_DRV_DROP_OTHER, +} wifi_rx_packet_fate; + +typedef enum { + FRAME_TYPE_UNKNOWN, + FRAME_TYPE_ETHERNET_II, + FRAME_TYPE_80211_MGMT, +} frame_type; + +typedef struct { + // The type of MAC-layer frame that this frame_info holds. + // - For data frames, use FRAME_TYPE_ETHERNET_II. + // - For management frames, use FRAME_TYPE_80211_MGMT. + // - If the type of the frame is unknown, use FRAME_TYPE_UNKNOWN. + frame_type payload_type; + + // The number of bytes included in |frame_content|. If the frame + // contents are missing (e.g. RX frame dropped in firmware), + // |frame_len| should be set to 0. + size_t frame_len; + + // Host clock when this frame was received by the driver (either + // outbound from the host network stack, or inbound from the + // firmware). + // - The timestamp should be taken from a clock which includes time + // the host spent suspended (e.g. ktime_get_boottime()). + // - If no host timestamp is available (e.g. RX frame was dropped in + // firmware), this field should be set to 0. + u32 driver_timestamp_usec; + + // Firmware clock when this frame was received by the firmware + // (either outbound from the host, or inbound from a remote + // station). + // - The timestamp should be taken from a clock which includes time + // firmware spent suspended (if applicable). + // - If no firmware timestamp is available (e.g. TX frame was + // dropped by driver), this field should be set to 0. + // - Consumers of |frame_info| should _not_ assume any + // synchronization between driver and firmware clocks. + u32 firmware_timestamp_usec; + + // Actual frame content. + // - Should be provided for TX frames originated by the host. + // - Should be provided for RX frames received by the driver. + // - Optionally provided for TX frames originated by firmware. (At + // discretion of HAL implementation.) + // - Optionally provided for RX frames dropped in firmware. (At + // discretion of HAL implementation.) + // - If frame content is not provided, |frame_len| should be set + // to 0. + union { + char ethernet_ii_bytes[MAX_FRAME_LEN_ETHERNET]; + char ieee_80211_mgmt_bytes[MAX_FRAME_LEN_80211_MGMT]; + } frame_content; +} frame_info; + +typedef struct { + // Prefix of MD5 hash of |frame_inf.frame_content|. If frame + // content is not provided, prefix of MD5 hash over the same data + // that would be in frame_content, if frame content were provided. + char md5_prefix[MD5_PREFIX_LEN]; + wifi_tx_packet_fate fate; + frame_info frame_inf; +} wifi_tx_report; + +typedef struct { + // Prefix of MD5 hash of |frame_inf.frame_content|. If frame + // content is not provided, prefix of MD5 hash over the same data + // that would be in frame_content, if frame content were provided. + char md5_prefix[MD5_PREFIX_LEN]; + wifi_rx_packet_fate fate; + frame_info frame_inf; +} wifi_rx_report; + +/** + API to start packet fate monitoring. + - Once stared, monitoring should remain active until HAL is unloaded. + - When HAL is unloaded, all packet fate buffers should be cleared. +*/ +wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle); + +/** + API to retrieve fates of outbound packets. + - HAL implementation should fill |tx_report_bufs| with fates of + _first_ min(n_requested_fates, actual packets) frames + transmitted for the most recent association. The fate reports + should follow the same order as their respective packets. + - HAL implementation may choose (but is not required) to include + reports for management frames. + - Packets reported by firmware, but not recognized by driver, + should be included. However, the ordering of the corresponding + reports is at the discretion of HAL implementation. + - Framework may call this API multiple times for the same association. + - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. + - Framework will allocate and free the referenced storage. +*/ +wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle, wifi_tx_report* tx_report_bufs, + size_t n_requested_fates, size_t* n_provided_fates); + +/** + API to retrieve fates of inbound packets. + - HAL implementation should fill |rx_report_bufs| with fates of + _first_ min(n_requested_fates, actual packets) frames + received for the most recent association. The fate reports + should follow the same order as their respective packets. + - HAL implementation may choose (but is not required) to include + reports for management frames. + - Packets reported by firmware, but not recognized by driver, + should be included. However, the ordering of the corresponding + reports is at the discretion of HAL implementation. + - Framework may call this API multiple times for the same association. + - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. + - Framework will allocate and free the referenced storage. +*/ +wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle, wifi_rx_report* rx_report_bufs, + size_t n_requested_fates, size_t* n_provided_fates); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_STATS_ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h new file mode 100644 index 0000000..3591b98 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_nan.h @@ -0,0 +1,2726 @@ +/* + * 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 __NAN_H__ +#define __NAN_H__ + +#include +#include +#include "wifi_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************************************************************** + * Neighbour Aware Network Service Structures and Functions + *****************************************************************************/ + +/* + Definitions + All multi-byte fields within all NAN protocol stack messages are assumed to be in Little Endian + order. +*/ + +typedef int NanVersion; +typedef u16 transaction_id; +typedef u32 NanDataPathId; + +#define NAN_MAC_ADDR_LEN 6 +#define NAN_MAJOR_VERSION 2 +#define NAN_MINOR_VERSION 0 +#define NAN_MICRO_VERSION 1 +#define NAN_MAX_SOCIAL_CHANNELS 3 + +/* NAN Maximum Lengths */ +#define NAN_MAX_SERVICE_NAME_LEN 255 +#define NAN_MAX_MATCH_FILTER_LEN 255 +#define NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024 +#define NAN_MAX_VSA_DATA_LEN 1024 +#define NAN_MAX_MESH_DATA_LEN 32 +#define NAN_MAX_INFRA_DATA_LEN 32 +#define NAN_MAX_CLUSTER_ATTRIBUTE_LEN 255 +#define NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42 +#define NAN_MAX_FAM_CHANNELS 32 +#define NAN_MAX_POSTDISCOVERY_LEN 5 +#define NAN_MAX_FRAME_DATA_LEN 504 +#define NAN_DP_MAX_APP_INFO_LEN 512 +#define NAN_ERROR_STR_LEN 255 +#define NAN_PMK_INFO_LEN 32 +#define NAN_MAX_SCID_BUF_LEN 1024 +#define NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN 1024 +#define NAN_SECURITY_MIN_PASSPHRASE_LEN 8 +#define NAN_SECURITY_MAX_PASSPHRASE_LEN 63 +#define NAN_MAX_CHANNEL_INFO_SUPPORTED 4 + +/* + Definition of various NanResponseType +*/ +typedef enum { + NAN_RESPONSE_ENABLED = 0, + NAN_RESPONSE_DISABLED = 1, + NAN_RESPONSE_PUBLISH = 2, + NAN_RESPONSE_PUBLISH_CANCEL = 3, + NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4, + NAN_RESPONSE_SUBSCRIBE = 5, + NAN_RESPONSE_SUBSCRIBE_CANCEL = 6, + NAN_RESPONSE_STATS = 7, + NAN_RESPONSE_CONFIG = 8, + NAN_RESPONSE_TCA = 9, + NAN_RESPONSE_ERROR = 10, + NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, + NAN_GET_CAPABILITIES = 12, + NAN_DP_INTERFACE_CREATE = 13, + NAN_DP_INTERFACE_DELETE = 14, + NAN_DP_INITIATOR_RESPONSE = 15, + NAN_DP_RESPONDER_RESPONSE = 16, + NAN_DP_END = 17 +} NanResponseType; + +/* NAN Publish Types */ +typedef enum { + NAN_PUBLISH_TYPE_UNSOLICITED = 0, + NAN_PUBLISH_TYPE_SOLICITED, + NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED +} NanPublishType; + +/* NAN Transmit Priorities */ +typedef enum { NAN_TX_PRIORITY_NORMAL = 0, NAN_TX_PRIORITY_HIGH } NanTxPriority; + +/* NAN Statistics Request ID Codes */ +typedef enum { + NAN_STATS_ID_DE_PUBLISH = 0, + NAN_STATS_ID_DE_SUBSCRIBE, + NAN_STATS_ID_DE_MAC, + NAN_STATS_ID_DE_TIMING_SYNC, + NAN_STATS_ID_DE_DW, + NAN_STATS_ID_DE +} NanStatsType; + +/* NAN Protocol Event ID Codes */ +typedef enum { + NAN_EVENT_ID_DISC_MAC_ADDR = 0, + NAN_EVENT_ID_STARTED_CLUSTER, + NAN_EVENT_ID_JOINED_CLUSTER +} NanDiscEngEventType; + +/* NAN Data Path type */ +typedef enum { NAN_DATA_PATH_UNICAST_MSG = 0, NAN_DATA_PATH_MULTICAST_MSG } NdpType; + +/* NAN Ranging Configuration */ +typedef enum { NAN_RANGING_DISABLE = 0, NAN_RANGING_ENABLE } NanRangingState; + +/* TCA Type */ +typedef enum { NAN_TCA_ID_CLUSTER_SIZE = 0 } NanTcaType; + +/* NAN Channel Info */ +typedef struct { + u32 channel; + u32 bandwidth; + u32 nss; +} NanChannelInfo; + +/* + Various NAN Protocol Response code +*/ +typedef enum { + /* NAN Protocol Response Codes */ + NAN_STATUS_SUCCESS = 0, + /* NAN Discovery Engine/Host driver failures */ + NAN_STATUS_INTERNAL_FAILURE = 1, + /* NAN OTA failures */ + NAN_STATUS_PROTOCOL_FAILURE = 2, + /* if the publish/subscribe id is invalid */ + NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3, + /* If we run out of resources allocated */ + NAN_STATUS_NO_RESOURCE_AVAILABLE = 4, + /* if invalid params are passed */ + NAN_STATUS_INVALID_PARAM = 5, + /* if the requestor instance id is invalid */ + NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6, + /* if the ndp id is invalid */ + NAN_STATUS_INVALID_NDP_ID = 7, + /* if NAN is enabled when wifi is turned off */ + NAN_STATUS_NAN_NOT_ALLOWED = 8, + /* if over the air ack is not received */ + NAN_STATUS_NO_OTA_ACK = 9, + /* If NAN is already enabled and we are try to re-enable the same */ + NAN_STATUS_ALREADY_ENABLED = 10, + /* If followup message internal queue is full */ + NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11, + /* Unsupported concurrency session enabled, NAN disabled notified */ + NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12 +} NanStatusType; + +/* NAN Transmit Types */ +typedef enum { NAN_TX_TYPE_BROADCAST = 0, NAN_TX_TYPE_UNICAST } NanTxType; + +/* NAN Subscribe Type */ +typedef enum { NAN_SUBSCRIBE_TYPE_PASSIVE = 0, NAN_SUBSCRIBE_TYPE_ACTIVE } NanSubscribeType; + +/* NAN Service Response Filter Attribute Bit */ +typedef enum { NAN_SRF_ATTR_BLOOM_FILTER = 0, NAN_SRF_ATTR_PARTIAL_MAC_ADDR } NanSRFType; + +/* NAN Service Response Filter Include Bit */ +typedef enum { NAN_SRF_INCLUDE_DO_NOT_RESPOND = 0, NAN_SRF_INCLUDE_RESPOND } NanSRFIncludeType; + +/* NAN Match indication type */ +typedef enum { + NAN_MATCH_ALG_MATCH_ONCE = 0, + NAN_MATCH_ALG_MATCH_CONTINUOUS, + NAN_MATCH_ALG_MATCH_NEVER +} NanMatchAlg; + +/* NAN Transmit Window Type */ +typedef enum { NAN_TRANSMIT_IN_DW = 0, NAN_TRANSMIT_IN_FAW } NanTransmitWindowType; + +/* NAN SRF State in Subscribe */ +typedef enum { NAN_DO_NOT_USE_SRF = 0, NAN_USE_SRF } NanSRFState; + +/* NAN Include SSI in MatchInd */ +typedef enum { + NAN_SSI_NOT_REQUIRED_IN_MATCH_IND = 0, + NAN_SSI_REQUIRED_IN_MATCH_IND +} NanSsiInMatchInd; + +/* NAN DP security Configuration */ +typedef enum { NAN_DP_CONFIG_NO_SECURITY = 0, NAN_DP_CONFIG_SECURITY } NanDataPathSecurityCfgStatus; + +typedef enum { NAN_QOS_NOT_REQUIRED = 0, NAN_QOS_REQUIRED } NanQosCfgStatus; + +/* Data request Responder's response */ +typedef enum { NAN_DP_REQUEST_ACCEPT = 0, NAN_DP_REQUEST_REJECT } NanDataPathResponseCode; + +/* NAN DP channel config options */ +typedef enum { + NAN_DP_CHANNEL_NOT_REQUESTED = 0, + NAN_DP_REQUEST_CHANNEL_SETUP, + NAN_DP_FORCE_CHANNEL_SETUP +} NanDataPathChannelCfg; + +/* Enable/Disable NAN Ranging Auto response */ +typedef enum { + NAN_RANGING_AUTO_RESPONSE_ENABLE = 1, + NAN_RANGING_AUTO_RESPONSE_DISABLE +} NanRangingAutoResponse; + +/* Enable/Disable NAN service range report */ +typedef enum { NAN_DISABLE_RANGE_REPORT = 1, NAN_ENABLE_RANGE_REPORT } NanRangeReport; + +/* NAN Range Response */ +typedef enum { + NAN_RANGE_REQUEST_ACCEPT = 1, + NAN_RANGE_REQUEST_REJECT, + NAN_RANGE_REQUEST_CANCEL +} NanRangeResponse; + +/* NAN Security Key Input Type*/ +typedef enum { + NAN_SECURITY_KEY_INPUT_PMK = 1, + NAN_SECURITY_KEY_INPUT_PASSPHRASE +} NanSecurityKeyInputType; + +typedef struct { + /* pmk length */ + u32 pmk_len; + /* + PMK: Info is optional in Discovery phase. + PMK info can be passed during + the NDP session. + */ + u8 pmk[NAN_PMK_INFO_LEN]; +} NanSecurityPmk; + +typedef struct { + /* passphrase length */ + u32 passphrase_len; + /* + passphrase info is optional in Discovery phase. + passphrase info can be passed during + the NDP session. + */ + u8 passphrase[NAN_SECURITY_MAX_PASSPHRASE_LEN]; +} NanSecurityPassPhrase; + +typedef struct { + NanSecurityKeyInputType key_type; + union { + NanSecurityPmk pmk_info; + NanSecurityPassPhrase passphrase_info; + } body; +} NanSecurityKeyInfo; + +/* NAN Security Cipher Suites Mask */ +#define NAN_CIPHER_SUITE_SHARED_KEY_NONE 0x00 +#define NAN_CIPHER_SUITE_SHARED_KEY_128_MASK 0x01 +#define NAN_CIPHER_SUITE_SHARED_KEY_256_MASK 0x02 +#define NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_128_MASK 0x04 +#define NAN_CIPHER_SUITE_PUBLIC_KEY_2WDH_256_MASK 0x08 + +/* NAN ranging indication condition MASKS */ +#define NAN_RANGING_INDICATE_CONTINUOUS_MASK 0x01 +#define NAN_RANGING_INDICATE_INGRESS_MET_MASK 0x02 +#define NAN_RANGING_INDICATE_EGRESS_MET_MASK 0x04 + +/* NAN schedule update reason MASKS */ +#define NAN_SCHEDULE_UPDATE_NSS_MASK 0x01 +#define NAN_SCHEDULE_UPDATE_CHANNEL_MASK 0x02 + +/* + Structure to set the Service Descriptor Extension + Attribute (SDEA) passed as part of NanPublishRequest/ + NanSubscribeRequest/NanMatchInd. +*/ +typedef struct { + /* + Optional configuration of Data Path Enable request. + configure flag determines whether configuration needs + to be passed or not. + */ + u8 config_nan_data_path; + NdpType ndp_type; + /* + NAN secuirty required flag to indicate + if the security is enabled or disabled + */ + NanDataPathSecurityCfgStatus security_cfg; + /* + NAN ranging required flag to indicate + if ranging is enabled on disabled + */ + NanRangingState ranging_state; + /* + Enable/Disable Ranging report, + when configured NanRangeReportInd received + */ + NanRangeReport range_report; + /* + NAN QOS required flag to indicate + if QOS is required or not. + */ + NanQosCfgStatus qos_cfg; +} NanSdeaCtrlParams; + +/* + Nan Ranging Peer Info in MatchInd +*/ +typedef struct { + /* + Distance to the NAN device with the MAC address indicated + with ranged mac address. + */ + u32 range_measurement_mm; + /* Ranging event matching the configuration of continuous/ingress/egress. */ + u32 ranging_event_type; +} NanRangeInfo; + +/* Nan/NDP Capabilites info */ +typedef struct { + u32 max_concurrent_nan_clusters; + u32 max_publishes; + u32 max_subscribes; + u32 max_service_name_len; + u32 max_match_filter_len; + u32 max_total_match_filter_len; + u32 max_service_specific_info_len; + u32 max_vsa_data_len; + u32 max_mesh_data_len; + u32 max_ndi_interfaces; + u32 max_ndp_sessions; + u32 max_app_info_len; + u32 max_queued_transmit_followup_msgs; + u32 ndp_supported_bands; + u32 cipher_suites_supported; + u32 max_scid_len; + bool is_ndp_security_supported; + u32 max_sdea_service_specific_info_len; + u32 max_subscribe_address; + u32 ndpe_attr_supported; + bool is_instant_mode_supported; +} NanCapabilities; + +/* + Nan accept policy: Per service basis policy + Based on this policy(ALL/NONE), responder side + will send ACCEPT/REJECT +*/ +typedef enum { + NAN_SERVICE_ACCEPT_POLICY_NONE = 0, + /* Default value */ + NAN_SERVICE_ACCEPT_POLICY_ALL +} NanServiceAcceptPolicy; + +/* + Host can send Vendor specific attributes which the Discovery Engine can + enclose in Beacons and/or Service Discovery frames transmitted. + Below structure is used to populate that. +*/ +typedef struct { + /* + 0 = transmit only in the next discovery window + 1 = transmit in next 16 discovery window + */ + u8 payload_transmit_flag; + /* + Below flags will determine in which all frames + the vendor specific attributes should be included + */ + u8 tx_in_discovery_beacon; + u8 tx_in_sync_beacon; + u8 tx_in_service_discovery; + /* Organizationally Unique Identifier */ + u32 vendor_oui; + /* + vendor specific attribute to be transmitted + vsa_len : Length of the vsa data. + */ + u32 vsa_len; + u8 vsa[NAN_MAX_VSA_DATA_LEN]; +} NanTransmitVendorSpecificAttribute; + +/* + Discovery Engine will forward any Vendor Specific Attributes + which it received as part of this structure. +*/ +/* Mask to determine on which frames attribute was received */ +#define RX_DISCOVERY_BEACON_MASK 0x01 +#define RX_SYNC_BEACON_MASK 0x02 +#define RX_SERVICE_DISCOVERY_MASK 0x04 +typedef struct { + /* + Frames on which this vendor specific attribute + was received. Mask defined above + */ + u8 vsa_received_on; + /* Organizationally Unique Identifier */ + u32 vendor_oui; + /* vendor specific attribute */ + u32 attr_len; + u8 vsa[NAN_MAX_VSA_DATA_LEN]; +} NanReceiveVendorSpecificAttribute; + +/* + NAN Beacon SDF Payload Received structure + Discovery engine sends the details of received Beacon or + Service Discovery Frames as part of this structure. +*/ +typedef struct { + /* Frame data */ + u32 frame_len; + u8 frame_data[NAN_MAX_FRAME_DATA_LEN]; +} NanBeaconSdfPayloadReceive; + +/* + Host can set the Periodic scan parameters for each of the + 3(6, 44, 149) Social channels. Only these channels are allowed + any other channels are rejected +*/ +typedef enum { + NAN_CHANNEL_24G_BAND = 0, + NAN_CHANNEL_5G_BAND_LOW, + NAN_CHANNEL_5G_BAND_HIGH +} NanChannelIndex; + +/* + Structure to set the Social Channel Scan parameters + passed as part of NanEnableRequest/NanConfigRequest +*/ +typedef struct { + /* + Dwell time of each social channel in milliseconds + NanChannelIndex corresponds to the respective channel + If time set to 0 then the FW default time will be used. + */ + u8 dwell_time[NAN_MAX_SOCIAL_CHANNELS]; // default value 200 msec + + /* + Scan period of each social channel in seconds + NanChannelIndex corresponds to the respective channel + If time set to 0 then the FW default time will be used. + */ + u16 scan_period[NAN_MAX_SOCIAL_CHANNELS]; // default value 20 sec +} NanSocialChannelScanParams; + +/* + Host can send Post Connectivity Capability attributes + to be included in Service Discovery frames transmitted + as part of this structure. +*/ +typedef struct { + /* + 0 = transmit only in the next discovery window + 1 = transmit in next 16 discovery window + */ + u8 payload_transmit_flag; + /* 1 - Wifi Direct supported 0 - Not supported */ + u8 is_wfd_supported; + /* 1 - Wifi Direct Services supported 0 - Not supported */ + u8 is_wfds_supported; + /* 1 - TDLS supported 0 - Not supported */ + u8 is_tdls_supported; + /* 1 - IBSS supported 0 - Not supported */ + u8 is_ibss_supported; + /* 1 - Mesh supported 0 - Not supported */ + u8 is_mesh_supported; + /* + 1 - NAN Device currently connect to WLAN Infra AP + 0 - otherwise + */ + u8 wlan_infra_field; +} NanTransmitPostConnectivityCapability; + +/* + Discovery engine providing the post connectivity capability + received. +*/ +typedef struct { + /* 1 - Wifi Direct supported 0 - Not supported */ + u8 is_wfd_supported; + /* 1 - Wifi Direct Services supported 0 - Not supported */ + u8 is_wfds_supported; + /* 1 - TDLS supported 0 - Not supported */ + u8 is_tdls_supported; + /* 1 - IBSS supported 0 - Not supported */ + u8 is_ibss_supported; + /* 1 - Mesh supported 0 - Not supported */ + u8 is_mesh_supported; + /* + 1 - NAN Device currently connect to WLAN Infra AP + 0 - otherwise + */ + u8 wlan_infra_field; +} NanReceivePostConnectivityCapability; + +/* + Indicates the availability interval duration associated with the + Availability Intervals Bitmap field +*/ +typedef enum { + NAN_DURATION_16MS = 0, + NAN_DURATION_32MS = 1, + NAN_DURATION_64MS = 2 +} NanAvailDuration; + +/* Further availability per channel information */ +typedef struct { + /* Defined above */ + NanAvailDuration entry_control; + /* + 1 byte field indicating the frequency band the NAN Device + will be available as defined in IEEE Std. 802.11-2012 + Annex E Table E-4 Global Operating Classes + */ + u8 class_val; + /* + 1 byte field indicating the channel the NAN Device + will be available. + */ + u8 channel; + /* + Map Id - 4 bit field which identifies the Further + availability map attribute. + */ + u8 mapid; + /* + divides the time between the beginnings of consecutive Discovery + Windows of a given NAN cluster into consecutive time intervals + of equal durations. The time interval duration is specified by + the Availability Interval Duration subfield of the Entry Control + field. + + A Nan device that sets the i-th bit of the Availability + Intervals Bitmap to 1 shall be present during the corresponding + i-th time interval in the operation channel indicated by the + Operating Class and Channel Number fields in the same Availability Entry. + + A Nan device that sets the i-th bit of the Availability Intervals Bitmap to + 0 may be present during the corresponding i-th time interval in the operation + channel indicated by the Operating Class and Channel Number fields in the same + Availability Entry. + + The size of the Bitmap is dependent upon the Availability Interval Duration + chosen in the Entry Control Field. The size can be either 1, 2 or 4 bytes long + + - Duration field is equal to 0, only AIB[0] is valid + - Duration field is equal to 1, only AIB [0] and AIB [1] is valid + - Duration field is equal to 2, AIB [0], AIB [1], AIB [2] and AIB [3] are valid + */ + u32 avail_interval_bitmap; +} NanFurtherAvailabilityChannel; + +/* + Further availability map which can be sent and received from + Discovery engine +*/ +typedef struct { + /* + Number of channels indicates the number of channel + entries which is part of fam + */ + u8 numchans; + NanFurtherAvailabilityChannel famchan[NAN_MAX_FAM_CHANNELS]; +} NanFurtherAvailabilityMap; + +/* + Host can send Post-Nan Discovery attributes which the Discovery Engine can + enclose in Service Discovery frames +*/ +/* Possible connection types in Post NAN Discovery attributes */ +typedef enum { + NAN_CONN_WLAN_INFRA = 0, + NAN_CONN_P2P_OPER = 1, + NAN_CONN_WLAN_IBSS = 2, + NAN_CONN_WLAN_MESH = 3, + NAN_CONN_FURTHER_SERVICE_AVAILABILITY = 4, + NAN_CONN_WLAN_RANGING = 5 +} NanConnectionType; + +/* Possible device roles in Post NAN Discovery attributes */ +typedef enum { + NAN_WLAN_INFRA_AP = 0, + NAN_WLAN_INFRA_STA = 1, + NAN_P2P_OPER_GO = 2, + NAN_P2P_OPER_DEV = 3, + NAN_P2P_OPER_CLI = 4 +} NanDeviceRole; + +/* Configuration params of NAN Ranging */ +typedef struct { + /* + Interval in milli sec between two ranging measurements. + If the Awake DW intervals in NanEnable/Config are larger + than the ranging intervals priority is given to Awake DW + Intervals. Only on a match the ranging is initiated for the + peer + */ + u32 ranging_interval_msec; + /* + Flags indicating the type of ranging event to be notified + NAN_RANGING_INDICATE_ MASKS are used to set these. + BIT0 - Continuous Ranging event notification. + BIT1 - Ingress distance is <=. + BIT2 - Egress distance is >=. + */ + u32 config_ranging_indications; + /* Ingress distance in millimeters (optional) */ + u32 distance_ingress_mm; + /* Egress distance in millmilliimeters (optional) */ + u32 distance_egress_mm; +} NanRangingCfg; + +/* NAN Ranging request's response */ +typedef struct { + /* Publish Id of an earlier Publisher */ + u16 publish_id; + /* + A 32 bit Requestor instance Id which is sent to the Application. + This Id will be used in subsequent RangeResponse on Subscribe side. + */ + u32 requestor_instance_id; + /* Peer MAC addr of Range Requestor */ + u8 peer_addr[NAN_MAC_ADDR_LEN]; + /* Response indicating ACCEPT/REJECT/CANCEL of Range Request */ + NanRangeResponse ranging_response; +} NanRangeResponseCfg; + +/* Structure of Post NAN Discovery attribute */ +typedef struct { + /* Connection type of the host */ + NanConnectionType type; + /* + Device role of the host based on + the connection type + */ + NanDeviceRole role; + /* + Flag to send the information as a single shot or repeated + for next 16 discovery windows + 0 - Single_shot + 1 - next 16 discovery windows + */ + u8 transmit_freq; + /* Duration of the availability bitmask */ + NanAvailDuration duration; + /* Availability interval bitmap based on duration */ + u32 avail_interval_bitmap; + /* + Mac address depending on the conn type and device role + -------------------------------------------------- + | Conn Type | Device Role | Mac address Usage | + -------------------------------------------------- + | WLAN_INFRA | AP/STA | BSSID of the AP | + -------------------------------------------------- + | P2P_OPER | GO | GO's address | + -------------------------------------------------- + | P2P_OPER | P2P_DEVICE | Address of who | + | | | would become GO | + -------------------------------------------------- + | WLAN_IBSS | NA | BSSID | + -------------------------------------------------- + | WLAN_MESH | NA | BSSID | + -------------------------------------------------- + */ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Mandatory mesh id value if connection type is WLAN_MESH + Mesh id contains 0-32 octet identifier and should be + as per IEEE Std.802.11-2012 spec. + */ + u16 mesh_id_len; + u8 mesh_id[NAN_MAX_MESH_DATA_LEN]; + /* + Optional infrastructure SSID if conn_type is set to + NAN_CONN_WLAN_INFRA + */ + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[NAN_MAX_INFRA_DATA_LEN]; +} NanTransmitPostDiscovery; + +/* + Discovery engine providing the structure of Post NAN + Discovery +*/ +typedef struct { + /* Connection type of the host */ + NanConnectionType type; + /* + Device role of the host based on + the connection type + */ + NanDeviceRole role; + /* Duration of the availability bitmask */ + NanAvailDuration duration; + /* Availability interval bitmap based on duration */ + u32 avail_interval_bitmap; + /* + Map Id - 4 bit field which identifies the Further + availability map attribute. + */ + u8 mapid; + /* + Mac address depending on the conn type and device role + -------------------------------------------------- + | Conn Type | Device Role | Mac address Usage | + -------------------------------------------------- + | WLAN_INFRA | AP/STA | BSSID of the AP | + -------------------------------------------------- + | P2P_OPER | GO | GO's address | + -------------------------------------------------- + | P2P_OPER | P2P_DEVICE | Address of who | + | | | would become GO | + -------------------------------------------------- + | WLAN_IBSS | NA | BSSID | + -------------------------------------------------- + | WLAN_MESH | NA | BSSID | + -------------------------------------------------- + */ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Mandatory mesh id value if connection type is WLAN_MESH + Mesh id contains 0-32 octet identifier and should be + as per IEEE Std.802.11-2012 spec. + */ + u16 mesh_id_len; + u8 mesh_id[NAN_MAX_MESH_DATA_LEN]; + /* + Optional infrastructure SSID if conn_type is set to + NAN_CONN_WLAN_INFRA + */ + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[NAN_MAX_INFRA_DATA_LEN]; +} NanReceivePostDiscovery; + +/* + NAN device level configuration of SDF and Sync beacons in both + 2.4/5GHz bands +*/ +typedef struct { + /* Configure 2.4GHz DW Band */ + u8 config_2dot4g_dw_band; + /* + Indicates the interval for Sync beacons and SDF's in 2.4GHz band. + Valid values of DW Interval are: 1, 2, 3, 4 and 5, 0 is reserved. + The SDF includes in OTA when enabled. The publish/subscribe period + values don't override the device level configurations. + */ + u32 dw_2dot4g_interval_val; // default value 1 + /* Configure 5GHz DW Band */ + u8 config_5g_dw_band; + /* + Indicates the interval for Sync beacons and SDF's in 5GHz band + Valid values of DW Interval are: 1, 2, 3, 4 and 5, 0 no wake up for + any interval. The SDF includes in OTA when enabled. The publish/subscribe + period values don't override the device level configurations. + */ + u32 dw_5g_interval_val; // default value 1 when 5G is enabled +} NanConfigDW; + +/* + Enable Request Message Structure + The NanEnableReq message instructs the Discovery Engine to enter an operational state +*/ +typedef struct { + /* Mandatory parameters below */ + u8 master_pref; // default value 0x02 + /* + A cluster_low value matching cluster_high indicates a request to join + a cluster with that value. If the requested cluster is not found the + device will start its own cluster. + */ + u16 cluster_low; // default value 0 + u16 cluster_high; // default value 0xFFFF + + /* + Optional configuration of Enable request. + Each of the optional parameters have configure flag which + determine whether configuration is to be passed or not. + */ + u8 config_support_5g; + u8 support_5g_val; // default value 0; turned off by default + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_sid_beacon; + u8 sid_beacon_val; // default value 0x01 + /* + The rssi values below should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_2dot4g_rssi_close; + u8 rssi_close_2dot4g_val; // default value -60 dBm + + u8 config_2dot4g_rssi_middle; + u8 rssi_middle_2dot4g_val; // default value -70 dBm + + u8 config_2dot4g_rssi_proximity; + u8 rssi_proximity_2dot4g_val; // default value -60dBm + + u8 config_hop_count_limit; + u8 hop_count_limit_val; // default value 0x02 + + /* + Defines 2.4G channel access support + 0 - No Support + 1 - Supported + */ + u8 config_2dot4g_support; + u8 support_2dot4g_val; // default value 0x01 + /* + Defines 2.4G channels will be used for sync/discovery beacons + 0 - 2.4G channels not used for beacons + 1 - 2.4G channels used for beacons + */ + u8 config_2dot4g_beacons; + u8 beacon_2dot4g_val; // default value 1 + /* + Defines 2.4G channels will be used for Service Discovery frames + 0 - 2.4G channels not used for Service Discovery frames + 1 - 2.4G channels used for Service Discovery frames + */ + u8 config_2dot4g_sdf; + u8 sdf_2dot4g_val; // default value 1 + /* + Defines 5G channels will be used for sync/discovery beacons + 0 - 5G channels not used for beacons + 1 - 5G channels used for beacons + */ + u8 config_5g_beacons; + u8 beacon_5g_val; // default value 1 when 5G is enabled + /* + Defines 5G channels will be used for Service Discovery frames + 0 - 5G channels not used for Service Discovery frames + 1 - 5G channels used for Service Discovery frames + */ + u8 config_5g_sdf; + u8 sdf_5g_val; // default value is 0 when 5G is enabled + /* + 1 byte value which defines the RSSI in + dBm for a close by Peer in 5 Ghz channels. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close; + u8 rssi_close_5g_val; // default value -60dBm when 5G is enabled + /* + 1 byte value which defines the RSSI value in + dBm for a close by Peer in 5 Ghz channels. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_middle; + u8 rssi_middle_5g_val; // default value -75dBm when 5G is enabled + /* + 1 byte value which defines the RSSI filter + threshold. Any Service Descriptors received above this + value that are configured for RSSI filtering will be dropped. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; // default value -60dBm when 5G is enabled + /* + 1 byte quantity which defines the window size over + which the “average RSSI†will be calculated over. + */ + u8 config_rssi_window_size; + u8 rssi_window_size_val; // default value 0x08 + /* + The 24 bit Organizationally Unique ID + the 8 bit Network Id. + */ + u8 config_oui; + u32 oui_val; // default value {0x51, 0x6F, 0x9A, 0x01, 0x00, 0x00} + /* + NAN Interface Address, If not configured the Discovery Engine + will generate a 6 byte Random MAC. + */ + u8 config_intf_addr; + u8 intf_addr_val[NAN_MAC_ADDR_LEN]; + /* + If set to 1, the Discovery Engine will enclose the Cluster + Attribute only sent in Beacons in a Vendor Specific Attribute + and transmit in a Service Descriptor Frame. + */ + u8 config_cluster_attribute_val; + /* + The periodicity in seconds between full scan’s to find any new + clusters available in the area. A Full scan should not be done + more than every 10 seconds and should not be done less than every + 30 seconds. + */ + u8 config_scan_params; + NanSocialChannelScanParams scan_params_val; + /* + 1 byte quantity which forces the Random Factor to a particular + value for all transmitted Sync/Discovery beacons + */ + u8 config_random_factor_force; + u8 random_factor_force_val; // default value off and set to 0x00 + /* + 1 byte quantity which forces the HC for all transmitted Sync and + Discovery Beacon NO matter the real HC being received over the + air. + */ + u8 config_hop_count_force; + u8 hop_count_force_val; // default value 0x00 + + /* channel frequency in MHz to enable Nan on */ + u8 config_24g_channel; + wifi_channel channel_24g_val; // default value channel 0x6 + + u8 config_5g_channel; + wifi_channel channel_5g_val; // default value channel 44 or 149 regulatory + // domain + /* Configure 2.4/5GHz DW */ + NanConfigDW config_dw; + + /* + By default discovery MAC address randomization is enabled + and default interval value is 30 minutes i.e. 1800 seconds. + The value 0 is used to disable MAC addr randomization. + */ + u8 config_disc_mac_addr_randomization; + u32 disc_mac_addr_rand_interval_sec; // default value 1800 sec + + /* + Set/Enable corresponding bits to disable Discovery indications: + BIT0 - Disable Discovery MAC Address Event. + BIT1 - Disable Started Cluster Event. + BIT2 - Disable Joined Cluster Event. + */ + u8 discovery_indication_cfg; // default value 0x0 + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_subscribe_sid_beacon; + u32 subscribe_sid_beacon_val; // default value 0x0 + /* + Discovery Beacon Interval config. + Default value is 128 msec in 2G DW and 176 msec in 2G/5G DW. + When 0 value is passed it is reset to default value of 128 or 176 msec. + */ + u8 config_discovery_beacon_int; + u32 discovery_beacon_interval; + /* + Enable Number of Spatial Streams. + This is NAN Power Optimization feature for NAN discovery. + */ + u8 config_nss; + // default value is implementation specific and passing 0 sets it to default + u32 nss; + /* + Enable device level NAN Ranging feature. + 0 - Disable + 1 - Enable + */ + u8 config_enable_ranging; + u32 enable_ranging; + /* + Enable/Disable DW Early termination. + 0 - Disable + 1 - Enable + */ + u8 config_dw_early_termination; + u32 enable_dw_termination; + /* + Indicate whether to use NDPE attribute to bring-up TCP/IP connection. + If config_ndpe_attr is not configured, the default behavior is + not using NDPE attr, and the capability is not advertised. + 0 - Not use + 1 - Use + */ + u8 config_ndpe_attr; + u32 use_ndpe_attr; + /* + Enable NAN v3.1 instant communication mode. + 0 - Disable + 1 - Enable + */ + u8 config_enable_instant_mode; + u32 enable_instant_mode; + /* + Config NAN v3.1 instant communication channel frequency selected over NFC/OOB method. + If dual band is supported default channel is 149 or 44 as per regulatory domain, + else channel 6 (send frequency in MHz). + Sometimes depending on country code retrictions, even 149/44 may be restricted + in those cases instant channel will be operational only in 2.4GHz. + Use wifi_get_usable_channels() API to get supported bands/channels before + Instant mode NFC handshake is triggered + */ + u8 config_instant_mode_channel; + wifi_channel instant_mode_channel; +} NanEnableRequest; + +/* + Publish Msg Structure + Message is used to request the DE to publish the Service Name + using the parameters passed into the Discovery Window +*/ +typedef struct { + u16 publish_id; /* id 0 means new publish, any other id is existing publish */ + u16 ttl; /* how many seconds to run for. 0 means forever until canceled */ + /* + period: Awake DW Interval for publish(service) + Indicates the interval between two Discovery Windows in which + the device supporting the service is awake to transmit or + receive the Service Discovery frames. + Valid values of Awake DW Interval are: 1, 2, 4, 8 and 16, value 0 will + default to 1. + */ + u16 period; + NanPublishType publish_type; /* 0= unsolicited, solicited = 1, 2= both */ + NanTxType tx_type; /* 0 = broadcast, 1= unicast if solicited publish */ + u8 publish_count; /* number of OTA Publish, 0 means forever until canceled */ + u16 service_name_len; /* length of service name */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; /* UTF-8 encoded string identifying the service */ + /* + Field which specifies how the matching indication to host is controlled. + 0 - Match and Indicate Once + 1 - Match and Indicate continuous + 2 - Match and Indicate never. This means don't indicate the match to the host. + 3 - Reserved + */ + NanMatchAlg publish_match_indicator; + + /* + Sequence of values + NAN Device that has invoked a Subscribe method corresponding to this Publish method + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of pairs which specify further response conditions + beyond the service name used to filter subscribe messages to respond to. + This is only needed when the PT is set to NAN_SOLICITED or NAN_SOLICITED_UNSOLICITED. + */ + u16 rx_match_filter_len; + u8 rx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Ordered sequence of pairs to be included in the Discovery Frame. + If present it is always sent in a Discovery Frame + */ + u16 tx_match_filter_len; + u8 tx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + flag which specifies that the Publish should use the configured RSSI + threshold and the received RSSI in order to filter requests + 0 – ignore the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + 1 – use the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + + */ + u8 rssi_threshold_flag; + + /* + 8-bit bitmap which allows the Host to associate this publish + with a particular Post-NAN Connectivity attribute + which has been sent down in a NanConfigureRequest/NanEnableRequest + message. If the DE fails to find a configured Post-NAN + connectivity attributes referenced by the bitmap, + the DE will return an error code to the Host. + If the Publish is configured to use a Post-NAN Connectivity + attribute and the Host does not refresh the Post-NAN Connectivity + attribute the Publish will be canceled and the Host will be sent + a PublishTerminatedIndication message. + */ + u8 connmap; + /* + Set/Enable corresponding bits to disable any indications that follow a publish. + BIT0 - Disable publish termination indication. + BIT1 - Disable match expired indication. + BIT2 - Disable followUp indication received (OTA). + BIT3 - Disable publishReplied indication. + */ + u8 recv_indication_cfg; + /* + Nan accept policy for the specific service(publish) + */ + NanServiceAcceptPolicy service_responder_policy; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* NAN configure service discovery extended attributes */ + NanSdeaCtrlParams sdea_params; + + /* NAN Ranging configuration */ + NanRangingCfg ranging_cfg; + + /* Enable/disable NAN serivce Ranging auto response mode */ + NanRangingAutoResponse ranging_auto_response; + + /* + When the ranging_auto_response_cfg is not set, NanRangeRequestInd is + received. Nan Range Response to Peer MAC Addr is notified to indicate + ACCEPT/REJECT/CANCEL to the requestor. + */ + NanRangeResponseCfg range_response_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanPublishRequest; + +/* + Publish Cancel Msg Structure + The PublishServiceCancelReq Message is used to request the DE to stop publishing + the Service Name identified by the Publish Id in the message. +*/ +typedef struct { + u16 publish_id; +} NanPublishCancelRequest; + +/* + NAN Subscribe Structure + The SubscribeServiceReq message is sent to the Discovery Engine + whenever the Upper layers would like to listen for a Service Name +*/ +typedef struct { + u16 subscribe_id; /* id 0 means new subscribe, non zero is existing subscribe */ + u16 ttl; /* how many seconds to run for. 0 means forever until canceled */ + /* + period: Awake DW Interval for subscribe(service) + Indicates the interval between two Discovery Windows in which + the device supporting the service is awake to transmit or + receive the Service Discovery frames. + Valid values of Awake DW Interval are: 1, 2, 4, 8 and 16, value 0 will + default to 1. + */ + u16 period; + + /* Flag which specifies how the Subscribe request shall be processed. */ + NanSubscribeType subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */ + + /* Flag which specifies on Active Subscribes how the Service Response Filter attribute is + * populated.*/ + NanSRFType serviceResponseFilter; /* 0 - Bloom Filter, 1 - MAC Addr */ + + /* Flag which specifies how the Service Response Filter Include bit is populated.*/ + NanSRFIncludeType + serviceResponseInclude; /* 0=Do not respond if in the Address Set, 1= Respond */ + + /* Flag which specifies if the Service Response Filter should be used when creating + * Subscribes.*/ + NanSRFState useServiceResponseFilter; /* 0=Do not send the Service Response Filter,1= send */ + + /* + Flag which specifies if the Service Specific Info is needed in + the Publish message before creating the MatchIndication + */ + NanSsiInMatchInd ssiRequiredForMatchIndication; /* 0=Not needed, 1= Required */ + + /* + Field which specifies how the matching indication to host is controlled. + 0 - Match and Indicate Once + 1 - Match and Indicate continuous + 2 - Match and Indicate never. This means don't indicate the match to the host. + 3 - Reserved + */ + NanMatchAlg subscribe_match_indicator; + + /* + The number of Subscribe Matches which should occur + before the Subscribe request is automatically terminated. + */ + u8 subscribe_count; /* If this value is 0 this field is not used by the DE.*/ + + u16 service_name_len; /* length of service name */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; /* UTF-8 encoded string identifying the service */ + + /* Sequence of values which further specify the published service beyond the service name*/ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of pairs used to filter out received publish discovery + messages. This can be sent both for a Passive or an Active Subscribe + */ + u16 rx_match_filter_len; + u8 rx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Ordered sequence of pairs included in the + Discovery Frame when an Active Subscribe is used. + */ + u16 tx_match_filter_len; + u8 tx_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + Flag which specifies that the Subscribe should use the configured RSSI + threshold and the received RSSI in order to filter requests + 0 – ignore the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + 1 – use the configured RSSI threshold when running a Service + Descriptor attribute or Service ID List Attribute through the DE matching logic. + + */ + u8 rssi_threshold_flag; + + /* + 8-bit bitmap which allows the Host to associate this Active + Subscribe with a particular Post-NAN Connectivity attribute + which has been sent down in a NanConfigureRequest/NanEnableRequest + message. If the DE fails to find a configured Post-NAN + connectivity attributes referenced by the bitmap, + the DE will return an error code to the Host. + If the Subscribe is configured to use a Post-NAN Connectivity + attribute and the Host does not refresh the Post-NAN Connectivity + attribute the Subscribe will be canceled and the Host will be sent + a SubscribeTerminatedIndication message. + */ + u8 connmap; + /* + NAN Interface Address, conforming to the format as described in + 8.2.4.3.2 of IEEE Std. 802.11-2012. + */ + u8 num_intf_addr_present; + u8 intf_addr[NAN_MAX_SUBSCRIBE_MAX_ADDRESS][NAN_MAC_ADDR_LEN]; + /* + Set/Enable corresponding bits to disable indications that follow a subscribe. + BIT0 - Disable subscribe termination indication. + BIT1 - Disable match expired indication. + BIT2 - Disable followUp indication received (OTA). + */ + u8 recv_indication_cfg; + + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* NAN configure service discovery extended attributes */ + NanSdeaCtrlParams sdea_params; + + /* NAN Ranging configuration */ + NanRangingCfg ranging_cfg; + + /* Enable/disable NAN serivce Ranging auto response mode */ + NanRangingAutoResponse ranging_auto_response; + + /* + When the ranging_auto_response_cfg is not set, NanRangeRequestInd is + received. Nan Range Response to Peer MAC Addr is notified to indicate + ACCEPT/REJECT/CANCEL to the requestor. + */ + NanRangeResponseCfg range_response_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanSubscribeRequest; + +/* + NAN Subscribe Cancel Structure + The SubscribeCancelReq Message is used to request the DE to stop looking for the Service Name. +*/ +typedef struct { + u16 subscribe_id; +} NanSubscribeCancelRequest; + +/* + Transmit follow up Structure + The TransmitFollowupReq message is sent to the DE to allow the sending of the + Service_Specific_Info to a particular MAC address. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + + /* + This Id is the Requestor Instance that is passed as + part of earlier MatchInd/FollowupInd message. + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; /* Unicast address */ + NanTxPriority priority; /* priority of the request 2=high */ + NanTransmitWindowType dw_or_faw; /* 0= send in a DW, 1=send in FAW */ + + /* + Sequence of values which further specify the published service beyond + the service name. + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + /* + Set/Enable corresponding bits to disable responses after followUp. + BIT0 - Disable followUp response from FW. + */ + u8 recv_indication_cfg; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanTransmitFollowupRequest; + +/* + Stats Request structure + The Discovery Engine can be queried at runtime by the Host processor for statistics + concerning various parts of the Discovery Engine. +*/ +typedef struct { + NanStatsType stats_type; /* NAN Statistics Request Type */ + u8 clear; /* 0= Do not clear the stats and return the current contents , 1= Clear the associated + stats */ +} NanStatsRequest; + +/* + Config Structure + The NanConfigurationReq message is sent by the Host to the + Discovery Engine in order to configure the Discovery Engine during runtime. +*/ +typedef struct { + u8 config_sid_beacon; + u8 sid_beacon; + u8 config_rssi_proximity; + u8 rssi_proximity; // default value -60dBm + u8 config_master_pref; + u8 master_pref; // default value 0x02 + /* + 1 byte value which defines the RSSI filter threshold. + Any Service Descriptors received above this value + that are configured for RSSI filtering will be dropped. + The rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; // default value -60dBm + /* + Optional configuration of Configure request. + Each of the optional parameters have configure flag which + determine whether configuration is to be passed or not. + */ + /* + 1 byte quantity which defines the window size over + which the “average RSSI†will be calculated over. + */ + u8 config_rssi_window_size; + u8 rssi_window_size_val; // default value 0x08 + /* + If set to 1, the Discovery Engine will enclose the Cluster + Attribute only sent in Beacons in a Vendor Specific Attribute + and transmit in a Service Descriptor Frame. + */ + u8 config_cluster_attribute_val; + /* + The periodicity in seconds between full scan’s to find any new + clusters available in the area. A Full scan should not be done + more than every 10 seconds and should not be done less than every + 30 seconds. + */ + u8 config_scan_params; + NanSocialChannelScanParams scan_params_val; + /* + 1 byte quantity which forces the Random Factor to a particular + value for all transmitted Sync/Discovery beacons + */ + u8 config_random_factor_force; + u8 random_factor_force_val; // default value 0x00 + /* + 1 byte quantity which forces the HC for all transmitted Sync and + Discovery Beacon NO matter the real HC being received over the + air. + */ + u8 config_hop_count_force; + u8 hop_count_force_val; // default value of 0 + /* NAN Post Connectivity Capability */ + u8 config_conn_capability; + NanTransmitPostConnectivityCapability conn_capability_val; + /* NAN Post Discover Capability */ + u8 num_config_discovery_attr; + NanTransmitPostDiscovery discovery_attr_val[NAN_MAX_POSTDISCOVERY_LEN]; + /* NAN Further availability Map */ + u8 config_fam; + NanFurtherAvailabilityMap fam_val; + /* Configure 2.4/5GHz DW */ + NanConfigDW config_dw; + /* + By default discovery MAC address randomization is enabled + and default interval value is 30 minutes i.e. 1800 seconds. + The value 0 is used to disable MAC addr randomization. + */ + u8 config_disc_mac_addr_randomization; + u32 disc_mac_addr_rand_interval_sec; // default value of 30 minutes + + /* + Set/Enable corresponding bits to disable Discovery indications: + BIT0 - Disable Discovery MAC Address Event. + BIT1 - Disable Started Cluster Event. + BIT2 - Disable Joined Cluster Event. + */ + u8 discovery_indication_cfg; // default value of 0 + /* + BIT 0 is used to specify to include Service IDs in Sync/Discovery beacons + 0 - Do not include SIDs in any beacons + 1 - Include SIDs in all beacons. + Rest 7 bits are count field which allows control over the number of SIDs + included in the Beacon. 0 means to include as many SIDs that fit into + the maximum allow Beacon frame size + */ + u8 config_subscribe_sid_beacon; + u32 subscribe_sid_beacon_val; // default value 0x0 + /* + Discovery Beacon Interval config. + Default value is 128 msec in 2G DW and 176 msec in 2G/5G DW. + When 0 value is passed it is reset to default value of 128 or 176 msec. + */ + u8 config_discovery_beacon_int; + u32 discovery_beacon_interval; + /* + Enable Number of Spatial Streams. + This is NAN Power Optimization feature for NAN discovery. + */ + u8 config_nss; + // default value is implementation specific and passing 0 sets it to default + u32 nss; + /* + Enable device level NAN Ranging feature. + 0 - Disable + 1 - Enable + */ + u8 config_enable_ranging; + u32 enable_ranging; + /* + Enable/Disable DW Early termination. + 0 - Disable + 1 - Enable + */ + u8 config_dw_early_termination; + u32 enable_dw_termination; + /* + Indicate whether to use NDPE attribute to bring-up TCP/IP connection + If config_ndpe_attr is not configured, the default behavior is + not using NDPE attr, and the capability is not advertised. + 0 - Not use + 1 - Use + */ + u8 config_ndpe_attr; + u32 use_ndpe_attr; + /* + Enable NAN v3.1 instant communication mode. + 0 - Disable + 1 - Enable + */ + u8 config_enable_instant_mode; + u32 enable_instant_mode; + /* + Config NAN v3.1 instant communication channel selected over NFC/OOB method. + If dual band is supported default channel is 149 or 44 as per regulatory domain, + else channel 6 (send frequency in MHz). + Sometimes depending on country code retrictions, even 149/44 may be restricted + in those cases instant channel will be operational only in 2.4GHz. + Use wifi_get_usable_channels() API to get supported bands/channels before + Instant mode NFC handshake is triggered + */ + u8 config_instant_mode_channel; + wifi_channel instant_mode_channel; +} NanConfigRequest; + +/* + TCA Structure + The Discovery Engine can be configured to send up Events whenever a configured + Threshold Crossing Alert (TCA) Type crosses an integral threshold in a particular direction. +*/ +typedef struct { + NanTcaType tca_type; /* Nan Protocol Threshold Crossing Alert (TCA) Codes */ + + /* flag which control whether or not an event is generated for the Rising direction */ + u8 rising_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which control whether or not an event is generated for the Falling direction */ + u8 falling_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which requests a previous TCA request to be cleared from the DE */ + u8 clear; /*0= Do not clear the TCA, 1=Clear the TCA */ + + /* 32 bit value which represents the threshold to be used.*/ + u32 threshold; +} NanTCARequest; + +/* + Beacon Sdf Payload Structure + The Discovery Engine can be configured to publish vendor specific attributes as part of + beacon or service discovery frame transmitted as part of this request.. +*/ +typedef struct { + /* + NanVendorAttribute will have the Vendor Specific Attribute which the + vendor wants to publish as part of Discovery or Sync or Service discovery frame + */ + NanTransmitVendorSpecificAttribute vsa; +} NanBeaconSdfPayloadRequest; + +/* Publish statistics. */ +typedef struct { + u32 validPublishServiceReqMsgs; + u32 validPublishServiceRspMsgs; + u32 validPublishServiceCancelReqMsgs; + u32 validPublishServiceCancelRspMsgs; + u32 validPublishRepliedIndMsgs; + u32 validPublishTerminatedIndMsgs; + u32 validActiveSubscribes; + u32 validMatches; + u32 validFollowups; + u32 invalidPublishServiceReqMsgs; + u32 invalidPublishServiceCancelReqMsgs; + u32 invalidActiveSubscribes; + u32 invalidMatches; + u32 invalidFollowups; + u32 publishCount; + u32 publishNewMatchCount; + u32 pubsubGlobalNewMatchCount; +} NanPublishStats; + +/* Subscribe statistics. */ +typedef struct { + u32 validSubscribeServiceReqMsgs; + u32 validSubscribeServiceRspMsgs; + u32 validSubscribeServiceCancelReqMsgs; + u32 validSubscribeServiceCancelRspMsgs; + u32 validSubscribeTerminatedIndMsgs; + u32 validSubscribeMatchIndMsgs; + u32 validSubscribeUnmatchIndMsgs; + u32 validSolicitedPublishes; + u32 validMatches; + u32 validFollowups; + u32 invalidSubscribeServiceReqMsgs; + u32 invalidSubscribeServiceCancelReqMsgs; + u32 invalidSubscribeFollowupReqMsgs; + u32 invalidSolicitedPublishes; + u32 invalidMatches; + u32 invalidFollowups; + u32 subscribeCount; + u32 bloomFilterIndex; + u32 subscribeNewMatchCount; + u32 pubsubGlobalNewMatchCount; +} NanSubscribeStats; + +/* NAN DW Statistics*/ +typedef struct { + /* RX stats */ + u32 validFrames; + u32 validActionFrames; + u32 validBeaconFrames; + u32 ignoredActionFrames; + u32 ignoredBeaconFrames; + u32 invalidFrames; + u32 invalidActionFrames; + u32 invalidBeaconFrames; + u32 invalidMacHeaders; + u32 invalidPafHeaders; + u32 nonNanBeaconFrames; + + u32 earlyActionFrames; + u32 inDwActionFrames; + u32 lateActionFrames; + + /* TX stats */ + u32 framesQueued; + u32 totalTRSpUpdates; + u32 completeByTRSp; + u32 completeByTp75DW; + u32 completeByTendDW; + u32 lateActionFramesTx; +} NanDWStats; + +/* NAN MAC Statistics. */ +typedef struct { + /* RX stats */ + u32 validFrames; + u32 validActionFrames; + u32 validBeaconFrames; + u32 ignoredActionFrames; + u32 ignoredBeaconFrames; + u32 invalidFrames; + u32 invalidActionFrames; + u32 invalidBeaconFrames; + u32 invalidMacHeaders; + u32 invalidPafHeaders; + u32 nonNanBeaconFrames; + + u32 earlyActionFrames; + u32 inDwActionFrames; + u32 lateActionFrames; + + /* TX stats */ + u32 framesQueued; + u32 totalTRSpUpdates; + u32 completeByTRSp; + u32 completeByTp75DW; + u32 completeByTendDW; + u32 lateActionFramesTx; + + u32 twIncreases; + u32 twDecreases; + u32 twChanges; + u32 twHighwater; + u32 bloomFilterIndex; +} NanMacStats; + +/* NAN Sync Statistics*/ +typedef struct { + u64 currTsf; + u64 myRank; + u64 currAmRank; + u64 lastAmRank; + u32 currAmBTT; + u32 lastAmBTT; + u8 currAmHopCount; + u8 currRole; + u16 currClusterId; + + u64 timeSpentInCurrRole; + u64 totalTimeSpentAsMaster; + u64 totalTimeSpentAsNonMasterSync; + u64 totalTimeSpentAsNonMasterNonSync; + u32 transitionsToAnchorMaster; + u32 transitionsToMaster; + u32 transitionsToNonMasterSync; + u32 transitionsToNonMasterNonSync; + u32 amrUpdateCount; + u32 amrUpdateRankChangedCount; + u32 amrUpdateBTTChangedCount; + u32 amrUpdateHcChangedCount; + u32 amrUpdateNewDeviceCount; + u32 amrExpireCount; + u32 mergeCount; + u32 beaconsAboveHcLimit; + u32 beaconsBelowRssiThresh; + u32 beaconsIgnoredNoSpace; + u32 beaconsForOurCluster; + u32 beaconsForOtherCluster; + u32 beaconCancelRequests; + u32 beaconCancelFailures; + u32 beaconUpdateRequests; + u32 beaconUpdateFailures; + u32 syncBeaconTxAttempts; + u32 syncBeaconTxFailures; + u32 discBeaconTxAttempts; + u32 discBeaconTxFailures; + u32 amHopCountExpireCount; + u32 ndpChannelFreq; + u32 ndpChannelFreq2; + u32 schedUpdateChannelFreq; +} NanSyncStats; + +/* NAN Misc DE Statistics */ +typedef struct { + u32 validErrorRspMsgs; + u32 validTransmitFollowupReqMsgs; + u32 validTransmitFollowupRspMsgs; + u32 validFollowupIndMsgs; + u32 validConfigurationReqMsgs; + u32 validConfigurationRspMsgs; + u32 validStatsReqMsgs; + u32 validStatsRspMsgs; + u32 validEnableReqMsgs; + u32 validEnableRspMsgs; + u32 validDisableReqMsgs; + u32 validDisableRspMsgs; + u32 validDisableIndMsgs; + u32 validEventIndMsgs; + u32 validTcaReqMsgs; + u32 validTcaRspMsgs; + u32 validTcaIndMsgs; + u32 invalidTransmitFollowupReqMsgs; + u32 invalidConfigurationReqMsgs; + u32 invalidStatsReqMsgs; + u32 invalidEnableReqMsgs; + u32 invalidDisableReqMsgs; + u32 invalidTcaReqMsgs; +} NanDeStats; + +/* Publish Response Message structure */ +typedef struct { + u16 publish_id; +} NanPublishResponse; + +/* Subscribe Response Message structure */ +typedef struct { + u16 subscribe_id; +} NanSubscribeResponse; + +/* + Stats Response Message structure + The Discovery Engine response to a request by the Host for statistics. +*/ +typedef struct { + NanStatsType stats_type; + union { + NanPublishStats publish_stats; + NanSubscribeStats subscribe_stats; + NanMacStats mac_stats; + NanSyncStats sync_stats; + NanDeStats de_stats; + NanDWStats dw_stats; + } data; +} NanStatsResponse; + +/* Response returned for Initiators Data request */ +typedef struct { + /* + Unique token Id generated on the initiator + side used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; +} NanDataPathRequestResponse; + +/* + NAN Response messages +*/ +typedef struct { + NanStatusType status; /* contains the result code */ + char nan_error[NAN_ERROR_STR_LEN]; /* Describe the NAN error type */ + NanResponseType response_type; /* NanResponseType Definitions */ + union { + NanPublishResponse publish_response; + NanSubscribeResponse subscribe_response; + NanStatsResponse stats_response; + NanDataPathRequestResponse data_request_response; + NanCapabilities nan_capabilities; + } body; +} NanResponseMsg; + +/* + Publish Replied Indication + The PublishRepliedInd Message is sent by the DE when an Active Subscribe is + received over the air and it matches a Solicited PublishServiceReq which had + been created with the replied_event_flag set. +*/ +typedef struct { + /* + A 32 bit Requestor Instance Id which is sent to the Application. + This Id will be sent in any subsequent UnmatchInd/FollowupInd + messages + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + /* + If RSSI filtering was configured in NanPublishRequest then this + field will contain the received RSSI value. 0 if not + */ + u8 rssi_value; +} NanPublishRepliedInd; + +/* + Publish Terminated + The PublishTerminatedInd message is sent by the DE whenever a Publish + terminates from a user-specified timeout or a unrecoverable error in the DE. +*/ +typedef struct { + /* Id returned during the initial Publish */ + u16 publish_id; + /* + For all user configured termination NAN_STATUS_SUCCESS + and no other reasons expected from firmware. + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanPublishTerminatedInd; + +/* + Match Indication + The MatchInd message is sent once per responding MAC address whenever + the Discovery Engine detects a match for a previous SubscribeServiceReq + or PublishServiceReq. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + A 32 bit Requestor Instance Id which is sent to the Application. + This Id will be sent in any subsequent UnmatchInd/FollowupInd + messages + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + + /* + Sequence of octets which were received in a Discovery Frame matching the + Subscribe Request. + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Ordered sequence of pairs received in the Discovery Frame + matching the Subscribe Request. + */ + u16 sdf_match_filter_len; + u8 sdf_match_filter[NAN_MAX_MATCH_FILTER_LEN]; + + /* + flag to indicate if the Match occurred in a Beacon Frame or in a + Service Discovery Frame. + 0 - Match occured in a Service Discovery Frame + 1 - Match occured in a Beacon Frame + */ + u8 match_occured_flag; + + /* + flag to indicate FW is out of resource and that it can no longer + track this Service Name. The Host still need to send the received + Match_Handle but duplicate MatchInd messages may be received on + this Handle until the resource frees up. + 0 - FW is caching this match + 1 - FW is unable to cache this match + */ + u8 out_of_resource_flag; + + /* + If RSSI filtering was configured in NanSubscribeRequest then this + field will contain the received RSSI value. 0 if not. + All rssi values should be specified without sign. + For eg: -70dBm should be specified as 70. + */ + u8 rssi_value; + + /* + optional attributes. Each optional attribute is associated with a flag + which specifies whether the attribute is valid or not + */ + /* NAN Post Connectivity Capability received */ + u8 is_conn_capability_valid; + NanReceivePostConnectivityCapability conn_capability; + + /* NAN Post Discover Capability */ + u8 num_rx_discovery_attr; + NanReceivePostDiscovery discovery_attr[NAN_MAX_POSTDISCOVERY_LEN]; + + /* NAN Further availability Map */ + u8 num_chans; + NanFurtherAvailabilityChannel famchan[NAN_MAX_FAM_CHANNELS]; + + /* NAN Cluster Attribute */ + u8 cluster_attribute_len; + u8 cluster_attribute[NAN_MAX_CLUSTER_ATTRIBUTE_LEN]; + + /* NAN Cipher Suite */ + u32 peer_cipher_type; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; + + /* Peer service discovery extended attributes */ + NanSdeaCtrlParams peer_sdea_params; + + /* + Ranging indication and NanMatchAlg are not tied. + Ex: NanMatchAlg can indicate Match_ONCE, but ranging + indications can be continuous. All ranging indications + depend on SDEA control parameters of ranging required for + continuous, and ingress/egress values in the ranging config. + Ranging indication data is notified if: + 1) Ranging required is enabled in SDEA. + range info notified continuous. + 2) if range_limit ingress/egress MASKS are enabled + notify once for ingress >= ingress_distance + and egress <= egress_distance, same for ingress_egress_both + 3) if the Awake DW intervals are higher than the ranging intervals, + priority is given to the device DW intervalsi. + */ + /* + Range Info includes: + 1) distance to the NAN device with the MAC address indicated + with ranged mac address. + 2) Ranging event matching the configuration of continuous/ingress/egress. + */ + NanRangeInfo range_info; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanMatchInd; + +/* + MatchExpired Indication + The MatchExpiredInd message is sent whenever the Discovery Engine detects that + a previously Matched Service has been gone for too long. If the previous + MatchInd message for this Publish/Subscribe Id had the out_of_resource_flag + set then this message will not be received +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + 32 bit value sent by the DE in a previous + MatchInd/FollowupInd to the application. + */ + u32 requestor_instance_id; +} NanMatchExpiredInd; + +/* + Subscribe Terminated + The SubscribeTerminatedInd message is sent by the DE whenever a + Subscribe terminates from a user-specified timeout or a unrecoverable error in the DE. +*/ +typedef struct { + /* Id returned during initial Subscribe */ + u16 subscribe_id; + /* + For all user configured termination NAN_STATUS_SUCCESS + and no other reasons expected from firmware. + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanSubscribeTerminatedInd; + +/* + Followup Indication Message + The FollowupInd message is sent by the DE to the Host whenever it receives a + Followup message from another peer. +*/ +typedef struct { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + /* + A 32 bit Requestor instance Id which is sent to the Application. + This Id will be used in subsequent UnmatchInd/FollowupInd messages. + */ + u32 requestor_instance_id; + u8 addr[NAN_MAC_ADDR_LEN]; + + /* Flag which the DE uses to decide if received in a DW or a FAW*/ + u8 dw_or_faw; /* 0=Received in a DW, 1 = Received in a FAW*/ + + /* + Sequence of values which further specify the published service beyond + the service name + */ + u16 service_specific_info_len; + u8 service_specific_info[NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* + Sequence of values indicating the service specific info in SDEA + */ + u16 sdea_service_specific_info_len; + u8 sdea_service_specific_info[NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN]; +} NanFollowupInd; + +/* + Event data notifying the Mac address of the Discovery engine. + which is reported as one of the Discovery engine event +*/ +typedef struct { + u8 addr[NAN_MAC_ADDR_LEN]; +} NanMacAddressEvent; + +/* + Event data notifying the Cluster address of the cluster + which is reported as one of the Discovery engine event +*/ +typedef struct { + u8 addr[NAN_MAC_ADDR_LEN]; +} NanClusterEvent; + +/* + Discovery Engine Event Indication + The Discovery Engine can inform the Host when significant events occur + The data following the EventId is dependent upon the EventId type. + In other words, each new event defined will carry a different + structure of information back to the host. +*/ +typedef struct { + NanDiscEngEventType event_type; /* NAN Protocol Event Codes */ + union { + /* + MacAddressEvent which will have 6 byte mac address + of the Discovery engine. + */ + NanMacAddressEvent mac_addr; + /* + Cluster Event Data which will be obtained when the + device starts a new cluster or joins a cluster. + The event data will have 6 byte octet string of the + cluster started or joined. + */ + NanClusterEvent cluster; + } data; +} NanDiscEngEventInd; + +/* Cluster size TCA event*/ +typedef struct { + /* size of the cluster*/ + u32 cluster_size; +} NanTcaClusterEvent; + +/* + NAN TCA Indication + The Discovery Engine can inform the Host when significant events occur. + The data following the TcaId is dependent upon the TcaId type. + In other words, each new event defined will carry a different structure + of information back to the host. +*/ +typedef struct { + NanTcaType tca_type; + /* flag which defines if the configured Threshold has risen above the threshold */ + u8 rising_direction_evt_flag; /* 0 - no event, 1 - event */ + + /* flag which defines if the configured Threshold has fallen below the threshold */ + u8 falling_direction_evt_flag; /* 0 - no event, 1 - event */ + union { + /* + This event in obtained when the cluser size threshold + is crossed. Event will have the cluster size + */ + NanTcaClusterEvent cluster; + } data; +} NanTCAInd; + +/* + NAN Disabled Indication + The NanDisableInd message indicates to the upper layers that the Discovery + Engine has flushed all state and has been shutdown. When this message is received + the DE is guaranteed to have left the NAN cluster it was part of and will have terminated + any in progress Publishes or Subscribes. +*/ +typedef struct { + /* + Following reasons expected: + NAN_STATUS_SUCCESS + NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanDisabledInd; + +/* + NAN Beacon or SDF Payload Indication + The NanBeaconSdfPayloadInd message indicates to the upper layers that information + elements were received either in a Beacon or SDF which needs to be delivered + outside of a Publish/Subscribe Handle. +*/ +typedef struct { + /* The MAC address of the peer which sent the attributes.*/ + u8 addr[NAN_MAC_ADDR_LEN]; + /* + Optional attributes. Each optional attribute is associated with a flag + which specifies whether the attribute is valid or not + */ + /* NAN Receive Vendor Specific Attribute*/ + u8 is_vsa_received; + NanReceiveVendorSpecificAttribute vsa; + + /* NAN Beacon or SDF Payload Received*/ + u8 is_beacon_sdf_payload_received; + NanBeaconSdfPayloadReceive data; +} NanBeaconSdfPayloadInd; + +/* + Event Indication notifying the + transmit followup in progress +*/ +typedef struct { + transaction_id id; + /* + Following reason codes returned: + NAN_STATUS_SUCCESS + NAN_STATUS_NO_OTA_ACK + NAN_STATUS_PROTOCOL_FAILURE + */ + NanStatusType reason; + char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */ +} NanTransmitFollowupInd; + +/* + Data request Initiator/Responder + app/service related info +*/ +typedef struct { + u16 ndp_app_info_len; + u8 ndp_app_info[NAN_DP_MAX_APP_INFO_LEN]; +} NanDataPathAppInfo; + +/* QoS configuration */ +typedef enum { NAN_DP_CONFIG_NO_QOS = 0, NAN_DP_CONFIG_QOS } NanDataPathQosCfg; + +/* Configuration params of Data request Initiator/Responder */ +typedef struct { + /* Status Indicating Security/No Security */ + NanDataPathSecurityCfgStatus security_cfg; + NanDataPathQosCfg qos_cfg; +} NanDataPathCfg; + +/* Nan Data Path Initiator requesting a data session */ +typedef struct { + /* + Unique Instance Id identifying the Responder's service. + This is same as publish_id notified on the subscribe side + in a publish/subscribe scenario + */ + u32 requestor_instance_id; /* Value 0 for no publish/subscribe */ + + /* Config flag for channel request */ + NanDataPathChannelCfg channel_request_type; + /* Channel frequency in MHz to start data-path */ + wifi_channel channel; + /* + Discovery MAC addr of the publisher/peer + */ + u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Interface name on which this NDP session is to be started. + This will be the same interface name provided during interface + create. + */ + char ndp_iface[IFNAMSIZ + 1]; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the Initiator */ + NanDataPathAppInfo app_info; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + /* length of service name */ + u32 service_name_len; + /* + UTF-8 encoded string identifying the service name. + The service name field is only used if a Nan discovery + is not associated with the NDP (out-of-band discovery). + */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathInitiatorRequest; + +/* + Data struct to initiate a data response on the responder side + for an indication received with a data request +*/ +typedef struct { + /* + Unique token Id generated on the initiator/responder + side used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* + Interface name on which this NDP session is to be started. + This will be the same interface name provided during interface + create. + */ + char ndp_iface[IFNAMSIZ + 1]; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the responder */ + NanDataPathAppInfo app_info; + /* Response Code indicating ACCEPT/REJECT/DEFER */ + NanDataPathResponseCode rsp_code; + /* NAN Cipher Suite Type */ + u32 cipher_type; + /* + Nan Security Key Info is optional in Discovery phase. + PMK or passphrase info can be passed during + the NDP session. + */ + NanSecurityKeyInfo key_info; + /* length of service name */ + u32 service_name_len; + /* + UTF-8 encoded string identifying the service name. + The service name field is only used if a Nan discovery + is not associated with the NDP (out-of-band discovery). + */ + u8 service_name[NAN_MAX_SERVICE_NAME_LEN]; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathIndicationResponse; + +/* NDP termination info */ +typedef struct { + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathEndRequest; + +/* + Event indication received on the + responder side when a Nan Data request or + NDP session is initiated on the Initiator side +*/ +typedef struct { + /* + Unique Instance Id corresponding to a service/session. + This is similar to the publish_id generated on the + publisher side + */ + u16 service_instance_id; + /* Discovery MAC addr of the peer/initiator */ + u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* Initiator/Responder Security/QoS configuration */ + NanDataPathCfg ndp_cfg; + /* App/Service information of the initiator */ + NanDataPathAppInfo app_info; + + /* Security Context Identifiers length */ + u32 scid_len; + /* + Security Context Identifier attribute contains PMKID + shall be included in NDP setup and response messages. + Security Context Identifier, Identifies the Security + Context. For NAN Shared Key Cipher Suite, this field + contains the 16 octet PMKID identifying the PMK used + for setting up the Secure Data Path. + */ + u8 scid[NAN_MAX_SCID_BUF_LEN]; +} NanDataPathRequestInd; + +/* + Event indication of data confirm is received on both + initiator and responder side confirming a NDP session +*/ +typedef struct { + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id; + /* + NDI mac address of the peer + (required to derive target ipv6 address) + */ + u8 peer_ndi_mac_addr[NAN_MAC_ADDR_LEN]; + /* App/Service information of Initiator/Responder */ + NanDataPathAppInfo app_info; + /* Response code indicating ACCEPT/REJECT/DEFER */ + NanDataPathResponseCode rsp_code; + /* + Reason code indicating the cause for REJECT. + NAN_STATUS_SUCCESS and NAN_STATUS_PROTOCOL_FAILURE are + expected reason codes. + */ + NanStatusType reason_code; + /* Number of channels for which info is indicated */ + u32 num_channels; + /* + Data indicating the Channel list and BW of the channel. + */ + NanChannelInfo channel_info[NAN_MAX_CHANNEL_INFO_SUPPORTED]; +} NanDataPathConfirmInd; + +/* + Event indication of schedule update is received on both + initiator and responder when a schedule change occurs +*/ +typedef struct { + /* + NMI mac address + */ + u8 peer_mac_addr[NAN_MAC_ADDR_LEN]; + /* + Reason code indicating the cause of schedule update. + BIT_0 NSS Update + BIT_1 Channel list update + */ + u32 schedule_update_reason_code; + /* Number of channels for which info is indicated */ + u32 num_channels; + /* + Data indicating the Channel list and BW of the channel. + */ + NanChannelInfo channel_info[NAN_MAX_CHANNEL_INFO_SUPPORTED]; + /* Number of NDP instance Ids */ + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathScheduleUpdateInd; + +/* + Event indication received on the + initiator/responder side terminating + a NDP session +*/ +typedef struct { + u8 num_ndp_instances; + /* + Unique token Id generated on the initiator/responder side + used for a NDP session between two NAN devices + */ + NanDataPathId ndp_instance_id[]; +} NanDataPathEndInd; + +/* + Event indicating Range Request received on the + Published side. +*/ +typedef struct { + u16 publish_id; /* id is existing publish */ + /* Range Requestor's MAC address */ + u8 range_req_intf_addr[NAN_MAC_ADDR_LEN]; +} NanRangeRequestInd; + +/* + Event indicating Range report on the + Published side. +*/ +typedef struct { + u16 publish_id; /* id is existing publish */ + /* Range Requestor's MAC address */ + u8 range_req_intf_addr[NAN_MAC_ADDR_LEN]; + /* + Distance to the NAN device with the MAC address indicated + with ranged mac address. + */ + u32 range_measurement_mm; +} NanRangeReportInd; + +/* Response and Event Callbacks */ +typedef struct { + /* NotifyResponse invoked to notify the status of the Request */ + void (*NotifyResponse)(transaction_id id, NanResponseMsg* rsp_data); + /* Callbacks for various Events */ + void (*EventPublishReplied)(NanPublishRepliedInd* event); + void (*EventPublishTerminated)(NanPublishTerminatedInd* event); + void (*EventMatch)(NanMatchInd* event); + void (*EventMatchExpired)(NanMatchExpiredInd* event); + void (*EventSubscribeTerminated)(NanSubscribeTerminatedInd* event); + void (*EventFollowup)(NanFollowupInd* event); + void (*EventDiscEngEvent)(NanDiscEngEventInd* event); + void (*EventDisabled)(NanDisabledInd* event); + void (*EventTca)(NanTCAInd* event); + void (*EventBeaconSdfPayload)(NanBeaconSdfPayloadInd* event); + void (*EventDataRequest)(NanDataPathRequestInd* event); + void (*EventDataConfirm)(NanDataPathConfirmInd* event); + void (*EventDataEnd)(NanDataPathEndInd* event); + void (*EventTransmitFollowup)(NanTransmitFollowupInd* event); + void (*EventRangeRequest)(NanRangeRequestInd* event); + void (*EventRangeReport)(NanRangeReportInd* event); + void (*EventScheduleUpdate)(NanDataPathScheduleUpdateInd* event); +} NanCallbackHandler; + +/**@brief nan_enable_request + * Enable NAN functionality + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanEnableRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_ALREADY_ENABLED + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NAN_NOT_ALLOWED + */ +wifi_error nan_enable_request(transaction_id id, wifi_interface_handle iface, + NanEnableRequest* msg); + +/**@brief nan_disbale_request + * Disable NAN functionality. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDisableRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_PROTOCOL_FAILURE + * + */ +wifi_error nan_disable_request(transaction_id id, wifi_interface_handle iface); + +/**@brief nan_publish_request + * Publish request to advertize a service + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanPublishRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NO_RESOURCE_AVAILABLE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + */ +wifi_error nan_publish_request(transaction_id id, wifi_interface_handle iface, + NanPublishRequest* msg); + +/**@brief nan_publish_cancel_request + * Cancel previous publish request + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanPublishCancelRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_publish_cancel_request(transaction_id id, wifi_interface_handle iface, + NanPublishCancelRequest* msg); + +/**@brief nan_subscribe_request + * Subscribe request to search for a service + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanSubscribeRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_NO_SPACE_AVAILABLE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + */ +wifi_error nan_subscribe_request(transaction_id id, wifi_interface_handle iface, + NanSubscribeRequest* msg); + +/**@brief nan_subscribe_cancel_request + * Cancel previous subscribe requests. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanSubscribeRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_subscribe_cancel_request(transaction_id id, wifi_interface_handle iface, + NanSubscribeCancelRequest* msg); + +/**@brief nan_transmit_followup_request + * NAN transmit follow up request + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanTransmitFollowupRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID + * NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID + * NAN_STATUS_FOLLOWUP_QUEUE_FULL + * @return Asynchronous TransmitFollowupInd CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_NO_OTA_ACK + */ +wifi_error nan_transmit_followup_request(transaction_id id, wifi_interface_handle iface, + NanTransmitFollowupRequest* msg); + +/**@brief nan_stats_request + * Request NAN statistics from Discovery Engine. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_INVALID_PARAM + */ +wifi_error nan_stats_request(transaction_id id, wifi_interface_handle iface, NanStatsRequest* msg); + +/**@brief nan_config_request + * NAN configuration request. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanConfigRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_config_request(transaction_id id, wifi_interface_handle iface, + NanConfigRequest* msg); + +/**@brief nan_tca_request + * Configure the various Threshold crossing alerts + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_tca_request(transaction_id id, wifi_interface_handle iface, NanTCARequest* msg); + +/**@brief nan_beacon_sdf_payload_request + * Set NAN Beacon or sdf payload to discovery engine. + * This instructs the Discovery Engine to begin publishing the + * received payload in any Beacon or Service Discovery Frame transmitted + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanStatsRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_beacon_sdf_payload_request(transaction_id id, wifi_interface_handle iface, + NanBeaconSdfPayloadRequest* msg); + +/* Register NAN callbacks. */ +wifi_error nan_register_handler(wifi_interface_handle iface, NanCallbackHandler handlers); + +/* Get NAN HAL version. */ +wifi_error nan_get_version(wifi_handle handle, NanVersion* version); + +/**@brief nan_get_capabilities + * Get NAN Capabilities + * + * @param transaction_id: + * @param wifi_interface_handle: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + */ +/* Get NAN capabilities. */ +wifi_error nan_get_capabilities(transaction_id id, wifi_interface_handle iface); + +/* ========== Nan Data Path APIs ================ */ +/**@brief nan_data_interface_create + * Create NAN Data Interface. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param iface_name: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_data_interface_create(transaction_id id, wifi_interface_handle iface, + char* iface_name); + +/**@brief nan_data_interface_delete + * Delete NAN Data Interface. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param iface_name: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + */ +wifi_error nan_data_interface_delete(transaction_id id, wifi_interface_handle iface, + char* iface_name); + +/**@brief nan_data_request_initiator + * Initiate a NAN Data Path session. + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathInitiatorRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID + */ +wifi_error nan_data_request_initiator(transaction_id id, wifi_interface_handle iface, + NanDataPathInitiatorRequest* msg); + +/**@brief nan_data_indication_response + * Response to a data indication received + * corresponding to a NDP session. An indication + * is received with a data request and the responder + * will send a data response + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathIndicationResponse: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_NDP_ID + */ +wifi_error nan_data_indication_response(transaction_id id, wifi_interface_handle iface, + NanDataPathIndicationResponse* msg); + +/**@brief nan_data_end + * NDL termination request: from either Initiator/Responder + * + * @param transaction_id: + * @param wifi_interface_handle: + * @param NanDataPathEndRequest: + * @return Synchronous wifi_error + * @return Asynchronous NotifyResponse CB return + * NAN_STATUS_SUCCESS + * NAN_STATUS_INVALID_PARAM + * NAN_STATUS_INTERNAL_FAILURE + * NAN_STATUS_PROTOCOL_FAILURE + * NAN_STATUS_INVALID_NDP_ID + */ +wifi_error nan_data_end(transaction_id id, wifi_interface_handle iface, NanDataPathEndRequest* msg); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NAN_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h new file mode 100644 index 0000000..0c69e39 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_offload.h @@ -0,0 +1,30 @@ +#include "wifi_hal.h" + +#ifndef __WIFI_HAL_OFFLOAD_H +#define __WIFI_HAL_OFFLOAD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define ETHER_ADDR_LEN 6 // Ethernet frame address length +#define N_AVAIL_ID 3 // available mkeep_alive IDs from 1 to 3 +#define MKEEP_ALIVE_IP_PKT_MAX 256 // max size of IP packet for keep alive + +/** + * Send specified keep alive packet periodically. + */ +wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface, + u16 ether_type, u8* ip_packet, u16 ip_packet_len, + u8* src_mac_addr, u8* dst_mac_addr, u32 period_msec); + +/** + * Stop sending keep alive packet. + */ +wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__WIFI_HAL_OFFLOAD_H */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h new file mode 100644 index 0000000..994bb18 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hal_legacy/wifi_twt.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2020 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 __WIFI_HAL_TWT_H__ +#define __WIFI_HAL_TWT_H__ + +#include "wifi_hal.h" + +typedef struct { + u8 requester_supported; // 0 for not supporting requester + u8 responder_supported; // 0 for not supporting responder + u8 broadcast_twt_supported; // 0 for not supporting broadcast TWT + u8 flexibile_twt_supported; // 0 for not supporting flexible TWT +} TwtCapability; + +typedef struct { + TwtCapability device_capability; + TwtCapability peer_capability; +} TwtCapabilitySet; + +// For all optional fields below, if no value specify -1 +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT + u8 trigger_type; // 0 for non-triggered TWT, 1 for triggered TWT + s32 wake_dur_us; // Proposed wake duration in us + s32 wake_int_us; // Average wake interval in us + s32 wake_int_min_us; // Min wake interval in us. Optional. + s32 wake_int_max_us; // Max wake interval in us. Optional. + s32 wake_dur_min_us; // Min wake duration in us. Optional. + s32 wake_dur_max_us; // Max wake duration in us. Optional. + s32 avg_pkt_size; // Average bytes of each packet to send in each wake + // duration. Optional. + s32 avg_pkt_num; // Average number of packets to send in each wake + // duration. Optional. + s32 wake_time_off_us; // First wake duration time offset in us. Optional. +} TwtSetupRequest; + +typedef enum { + TWT_SETUP_SUCCESS = 0, // TWT setup is accepted. + TWT_SETUP_REJECT = 1, // TWT setup is rejected by AP. + TWT_SETUP_TIMEOUT = 2, // TWT setup response from AP times out. + TWT_SETUP_IE = 3, // AP sent TWT Setup IE parsing failure. + TWT_SETUP_PARAMS = 4, // AP sent TWT Setup IE Parameters invalid. + TWT_SETUP_ERROR = 255, // Generic error +} TwtSetupReasonCode; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 status; // 0 for success, non-zero for failure + TwtSetupReasonCode reason_code; + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT + u8 trigger_type; // 0 for non-triggered TWT, 1 for triggered TWT + s32 wake_dur_us; // Proposed wake duration in us + s32 wake_int_us; // Average wake interval in us + s32 wake_time_off_us; // First wake duration time offset in us. +} TwtSetupResponse; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setp request, 1 for all TWT + u8 negotiation_type; // 0 for individual TWT, 1 for broadcast TWT +} TwtTeardownRequest; + +typedef enum { + TWT_TD_RC_HOST = 0, // Teardown triggered by Host + TWT_TD_RC_PEER = 1, // Peer initiated teardown + TWT_TD_RC_MCHAN = 2, // Teardown due to MCHAN Active + TWT_TD_RC_MCNX = 3, // Teardown due to MultiConnection + TWT_TD_RC_CSA = 4, // Teardown due to CSA + TWT_TD_RC_BTCX = 5, // Teardown due to BT Coex + TWT_TD_RC_SETUP_FAIL = 6, // Setup fails midway. Teardown all connections + TWT_TD_RC_SCHED = 7, // Teardown by TWT Scheduler + TWT_TD_RC_ERROR = 255, // Generic error cases +} TwtTeardownReason; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setp request, 1 for all TWT + u8 status; // 0 for success, non-zero for failure + TwtTeardownReason reason; +} TwtTeardownCompletion; + +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setup request, 1 for all TWT + s32 resume_time_us; // If -1, TWT is suspended for indefinite time. + // Otherwise, TWT is suspended for resume_time_us +} TwtInfoFrameRequest; + +typedef enum { + TWT_INFO_RC_HOST = 0, // Host initiated TWT Info frame */ + TWT_INFO_RC_PEER = 1, // Peer initiated TWT Info frame + TWT_INFO_RC_ERROR = 2, // Generic error conditions */ +} TwtInfoFrameReason; + +// TWT Info frame triggered externally. +// Device should not send TwtInfoFrameReceived to Host for internally +// triggered TWT Info frame during SCAN, MCHAN operations. +typedef struct { + u8 config_id; // An unique ID for an individual TWT request + u8 all_twt; // 0 for individual setup request, 1 for all TWT + u8 status; // 0 for success, non-zero for failure + TwtInfoFrameReason reason; + u8 twt_resumed; // 1 - TWT resumed, 0 - TWT suspended +} TwtInfoFrameReceived; + +typedef struct { + u8 config_id; + u32 avg_pkt_num_tx; // Average number of Tx packets in each wake duration. + u32 avg_pkt_num_rx; // Average number of Rx packets in each wake duration. + u32 avg_tx_pkt_size; // Average bytes per Rx packet in each wake duration. + u32 avg_rx_pkt_size; // Average bytes per Rx packet in each wake duration. + u32 avg_eosp_dur_us; // Average duration of early terminated SP + u32 eosp_count; // Count of early terminations + u32 num_sp; // Count of service period (SP), also known as wake duration. +} TwtStats; + +// Asynchronous notification from the device. +// For example, TWT was torn down by the device and later when the device is +// ready, it can send this async notification. +// This can be expandable in future. +typedef enum { + TWT_NOTIF_ALLOW_TWT = 1, // Device ready to process TWT Setup request +} TwtNotification; + +typedef struct { + TwtNotification notification; +} TwtDeviceNotify; + +// Callbacks for various TWT responses and events +typedef struct { + // Callback for TWT setup response + void (*EventTwtSetupResponse)(TwtSetupResponse* event); + // Callback for TWT teardown completion + void (*EventTwtTeardownCompletion)(TwtTeardownCompletion* event); + // Callback for TWT info frame received event + void (*EventTwtInfoFrameReceived)(TwtInfoFrameReceived* event); + // Callback for TWT notification from the device + void (*EventTwtDeviceNotify)(TwtDeviceNotify* event); +} TwtCallbackHandler; + +#endif /* __WIFI_HAL_TWT_H__ */ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h new file mode 100644 index 0000000..aab0ae5 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_callback_util.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017 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 HIDL_CALLBACK_UTIL_H_ +#define HIDL_CALLBACK_UTIL_H_ + +#include + +#include +#include + +namespace { +// Type of callback invoked by the death handler. +using on_death_cb_function = std::function; + +// Private class used to keep track of death of individual +// callbacks stored in HidlCallbackHandler. +template +class HidlDeathHandler : public android::hardware::hidl_death_recipient { + public: + HidlDeathHandler(const on_death_cb_function& user_cb_function) + : cb_function_(user_cb_function) {} + ~HidlDeathHandler() = default; + + // Death notification for callbacks. + void serviceDied(uint64_t cookie, + const android::wp& /* who */) override { + cb_function_(cookie); + } + + private: + on_death_cb_function cb_function_; + + DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler); +}; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_callback_util { +template +// Provides a class to manage callbacks for the various HIDL interfaces and +// handle the death of the process hosting each callback. +class HidlCallbackHandler { + public: + HidlCallbackHandler() + : death_handler_(new HidlDeathHandler( + std::bind(&HidlCallbackHandler::onObjectDeath, this, std::placeholders::_1))) {} + ~HidlCallbackHandler() = default; + + bool addCallback(const sp& cb) { + // TODO(b/33818800): Can't compare proxies yet. So, use the cookie + // (callback proxy's raw pointer) to track the death of individual + // clients. + uint64_t cookie = reinterpret_cast(cb.get()); + for (const auto& s : cb_set_) { + if (interfacesEqual(cb, s)) { + LOG(ERROR) << "Duplicate death notification registration"; + return true; + } + } + if (!cb->linkToDeath(death_handler_, cookie)) { + LOG(ERROR) << "Failed to register death notification"; + return false; + } + cb_set_.insert(cb); + return true; + } + + const std::set>& getCallbacks() { return cb_set_; } + + // Death notification for callbacks. + void onObjectDeath(uint64_t cookie) { + CallbackType* cb = reinterpret_cast(cookie); + const auto& iter = cb_set_.find(cb); + if (iter == cb_set_.end()) { + LOG(ERROR) << "Unknown callback death notification received"; + return; + } + cb_set_.erase(iter); + LOG(DEBUG) << "Dead callback removed from list"; + } + + void invalidate() { + for (const sp& cb : cb_set_) { + if (!cb->unlinkToDeath(death_handler_)) { + LOG(ERROR) << "Failed to deregister death notification"; + } + } + cb_set_.clear(); + } + + private: + std::set> cb_set_; + sp> death_handler_; + + DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); +}; + +} // namespace hidl_callback_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_CALLBACK_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h new file mode 100644 index 0000000..a0efac2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_return_util.h @@ -0,0 +1,118 @@ +/* + * 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 HIDL_RETURN_UTIL_H_ +#define HIDL_RETURN_UTIL_H_ + +#include "hidl_sync_util.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_return_util { +using namespace android::hardware::wifi::V1_0; + +/** + * These utility functions are used to invoke a method on the provided + * HIDL interface object. + * These functions checks if the provided HIDL interface object is valid. + * a) if valid, Invokes the corresponding internal implementation function of + * the HIDL method. It then invokes the HIDL continuation callback with + * the status and any returned values. + * b) if invalid, invokes the HIDL continuation callback with the + * provided error status and default values. + */ +// Use for HIDL methods which return only an instance of WifiStatus. +template +Return validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(std::forward(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return only an instance of WifiStatus. +// This version passes the global lock acquired to the body of the method. +// Note: Only used by IWifi::stop() currently. +template +Return validateAndCallWithLock(ObjT* obj, WifiStatusCode status_code_if_invalid, + WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(&lock, std::forward(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and a single return +// value. +template +Return validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_pair = (obj->*work)(std::forward(args)...); + const WifiStatus& status = std::get<0>(ret_pair); + const auto& ret_value = std::get<1>(ret_pair); + hidl_cb(status, ret_value); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference::type()); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and 2 return +// values. +template +Return validateAndCall( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function& hidl_cb, Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_tuple = (obj->*work)(std::forward(args)...); + const WifiStatus& status = std::get<0>(ret_tuple); + const auto& ret_value1 = std::get<1>(ret_tuple); + const auto& ret_value2 = std::get<2>(ret_tuple); + hidl_cb(status, ret_value1, ret_value2); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference::type(), + typename std::remove_reference::type()); + } + return Void(); +} + +} // namespace hidl_return_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_RETURN_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp new file mode 100644 index 0000000..2112b26 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.cpp @@ -0,0 +1,3007 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "hidl_struct_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_struct_util { + +using V1_6::NanConfigRequestSupplemental; + +WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(legacy_hal::wifi_channel_width type); + +hidl_string safeConvertChar(const char* str, size_t max_len) { + const char* c = str; + size_t size = 0; + while (*c && (unsigned char)*c < 128 && size < max_len) { + ++size; + ++c; + } + return hidl_string(str, size); +} + +IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(uint32_t feature) { + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP; + case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP; + case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT; + case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT; + case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask convertLegacyLoggerFeatureToHidlStaIfaceCapability( + uint32_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED: + return HidlStaIfaceCaps::DEBUG_PACKET_FATE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(uint64_t feature) { + using HidlChipCaps = V1_5::IWifiChip::ChipCapabilityMask; + switch (feature) { + case WIFI_FEATURE_SET_TX_POWER_LIMIT: + return HidlChipCaps::SET_TX_POWER_LIMIT; + case WIFI_FEATURE_USE_BODY_HEAD_SAR: + return HidlChipCaps::USE_BODY_HEAD_SAR; + case WIFI_FEATURE_D2D_RTT: + return HidlChipCaps::D2D_RTT; + case WIFI_FEATURE_D2AP_RTT: + return HidlChipCaps::D2AP_RTT; + case WIFI_FEATURE_INFRA_60G: + return HidlChipCaps::WIGIG; + case WIFI_FEATURE_SET_LATENCY_MODE: + return HidlChipCaps::SET_LATENCY_MODE; + case WIFI_FEATURE_P2P_RAND_MAC: + return HidlChipCaps::P2P_RAND_MAC; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask convertLegacyFeatureToHidlStaIfaceCapability( + uint64_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case WIFI_FEATURE_GSCAN: + return HidlStaIfaceCaps::BACKGROUND_SCAN; + case WIFI_FEATURE_LINK_LAYER_STATS: + return HidlStaIfaceCaps::LINK_LAYER_STATS; + case WIFI_FEATURE_RSSI_MONITOR: + return HidlStaIfaceCaps::RSSI_MONITOR; + case WIFI_FEATURE_CONTROL_ROAMING: + return HidlStaIfaceCaps::CONTROL_ROAMING; + case WIFI_FEATURE_IE_WHITELIST: + return HidlStaIfaceCaps::PROBE_IE_WHITELIST; + case WIFI_FEATURE_SCAN_RAND: + return HidlStaIfaceCaps::SCAN_RAND; + case WIFI_FEATURE_INFRA_5G: + return HidlStaIfaceCaps::STA_5G; + case WIFI_FEATURE_HOTSPOT: + return HidlStaIfaceCaps::HOTSPOT; + case WIFI_FEATURE_PNO: + return HidlStaIfaceCaps::PNO; + case WIFI_FEATURE_TDLS: + return HidlStaIfaceCaps::TDLS; + case WIFI_FEATURE_TDLS_OFFCHANNEL: + return HidlStaIfaceCaps::TDLS_OFFCHANNEL; + case WIFI_FEATURE_CONFIG_NDO: + return HidlStaIfaceCaps::ND_OFFLOAD; + case WIFI_FEATURE_MKEEP_ALIVE: + return HidlStaIfaceCaps::KEEP_ALIVE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature); + } + } + std::vector features = {WIFI_FEATURE_SET_TX_POWER_LIMIT, + WIFI_FEATURE_USE_BODY_HEAD_SAR, + WIFI_FEATURE_D2D_RTT, + WIFI_FEATURE_D2AP_RTT, + WIFI_FEATURE_INFRA_60G, + WIFI_FEATURE_SET_LATENCY_MODE, + WIFI_FEATURE_P2P_RAND_MAC}; + for (const auto feature : features) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature); + } + } + + // There are no flags for these 3 in the legacy feature set. Adding them to + // the set because all the current devices support it. + *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA; + *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS; + *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS; + return true; +} + +WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(uint32_t flag) { + switch (flag) { + case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES: + return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES; + case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES: + return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES; + }; + CHECK(false) << "Unknown legacy flag: " << flag; + return {}; +} + +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status) { + if (!hidl_status) { + return false; + } + *hidl_status = {}; + hidl_status->ringName = safeConvertChar(reinterpret_cast(legacy_status.name), + sizeof(legacy_status.name)); + hidl_status->flags = 0; + for (const auto flag : + {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) { + if (flag & legacy_status.flags) { + hidl_status->flags |= static_cast::type>( + convertLegacyDebugRingBufferFlagsToHidl(flag)); + } + } + hidl_status->ringId = legacy_status.ring_id; + hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size; + // Calculate free size of the ring the buffer. We don't need to send the + // exact read/write pointers that were there in the legacy HAL interface. + if (legacy_status.written_bytes >= legacy_status.read_bytes) { + hidl_status->freeSizeInBytes = legacy_status.ring_buffer_byte_size - + (legacy_status.written_bytes - legacy_status.read_bytes); + } else { + hidl_status->freeSizeInBytes = legacy_status.read_bytes - legacy_status.written_bytes; + } + hidl_status->verboseLevel = legacy_status.verbose_level; + return true; +} + +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector& legacy_status_vec, + std::vector* hidl_status_vec) { + if (!hidl_status_vec) { + return false; + } + *hidl_status_vec = {}; + for (const auto& legacy_status : legacy_status_vec) { + WifiDebugRingBufferStatus hidl_status; + if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status, &hidl_status)) { + return false; + } + hidl_status_vec->push_back(hidl_status); + } + return true; +} + +bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + hidl_stats->totalCmdEventWakeCnt = legacy_stats.wake_reason_cnt.total_cmd_event_wake; + hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt; + hidl_stats->totalDriverFwLocalWakeCnt = legacy_stats.wake_reason_cnt.total_driver_fw_local_wake; + hidl_stats->driverFwLocalWakeCntPerType = legacy_stats.driver_fw_local_wake_cnt; + hidl_stats->totalRxPacketWakeCnt = legacy_stats.wake_reason_cnt.total_rx_data_wake; + hidl_stats->rxPktWakeDetails.rxUnicastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt; + hidl_stats->rxPktWakeDetails.rxMulticastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt; + hidl_stats->rxPktWakeDetails.rxBroadcastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt; + hidl_stats->rxIcmpPkWakeDetails.icmpPkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ra = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra; + hidl_stats->rxIcmpPkWakeDetails.icmp6Na = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ns = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns; + return true; +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + }; + CHECK(false); +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + // Those are the supported scenarios for V1_2 + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; + }; + CHECK(false); +} + +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + V1_3::IWifiChip::LatencyMode hidl_latency_mode) { + switch (hidl_latency_mode) { + case V1_3::IWifiChip::LatencyMode::NORMAL: + return legacy_hal::WIFI_LATENCY_MODE_NORMAL; + case V1_3::IWifiChip::LatencyMode::LOW: + return legacy_hal::WIFI_LATENCY_MODE_LOW; + } + CHECK(false); +} + +bool convertLegacyWifiMacInfoToHidl( + const legacy_hal::WifiMacInfo& legacy_mac_info, + V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { + if (!hidl_radio_mode_info) { + return false; + } + *hidl_radio_mode_info = {}; + + hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id; + // Convert from bitmask of bands in the legacy HAL to enum value in + // the HIDL interface. + if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_6GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ; + } else { + hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_UNSPECIFIED; + } + std::vector iface_info_vec; + for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) { + V1_2::IWifiChipEventCallback::IfaceInfo iface_info; + iface_info.name = legacy_iface_info.name; + iface_info.channel = legacy_iface_info.channel; + iface_info_vec.push_back(iface_info); + } + hidl_radio_mode_info->ifaceInfos = iface_info_vec; + return true; +} + +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) { + switch (hidl_band) { + case V1_5::WifiBand::BAND_24GHZ: + return legacy_hal::WLAN_MAC_2_4_BAND; + case V1_5::WifiBand::BAND_5GHZ: + case V1_5::WifiBand::BAND_5GHZ_DFS: + case V1_5::WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WLAN_MAC_5_0_BAND; + case V1_5::WifiBand::BAND_24GHZ_5GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND); + case V1_5::WifiBand::BAND_6GHZ: + return legacy_hal::WLAN_MAC_6_0_BAND; + case V1_5::WifiBand::BAND_5GHZ_6GHZ: + return (legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ: + case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND); + case V1_5::WifiBand::BAND_60GHZ: + return legacy_hal::WLAN_MAC_60_0_BAND; + default: + return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND | + legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND); + } +} + +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band) { + switch (band) { + case legacy_hal::WLAN_MAC_2_4_BAND: + return V1_5::WifiBand::BAND_24GHZ; + case legacy_hal::WLAN_MAC_5_0_BAND: + return V1_5::WifiBand::BAND_5GHZ; + case legacy_hal::WLAN_MAC_6_0_BAND: + return V1_5::WifiBand::BAND_6GHZ; + case legacy_hal::WLAN_MAC_60_0_BAND: + return V1_5::WifiBand::BAND_60GHZ; + default: + return V1_5::WifiBand::BAND_UNSPECIFIED; + } +} + +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) { + uint32_t legacy_iface_mask = 0; + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_NAN) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_TDLS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_MESH) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH); + } + if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_IBSS) { + legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS); + } + return legacy_iface_mask; +} + +uint32_t convertLegacyWifiInterfaceModeToHidl(uint32_t legacy_iface_mask) { + uint32_t hidl_iface_mask = 0; + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_STA; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_NAN; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_TDLS; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_MESH; + } + if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) { + hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_IBSS; + } + return hidl_iface_mask; +} + +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask) { + uint32_t legacy_filter_mask = 0; + if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) { + legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; + } + if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CONCURRENCY) { + legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; + } + if (hidl_filter_mask & V1_6::IWifiChip::UsableChannelFilter::NAN_INSTANT_MODE) { + legacy_filter_mask |= WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE; + } + return legacy_filter_mask; +} + +bool convertLegacyWifiUsableChannelToHidl( + const legacy_hal::wifi_usable_channel& legacy_usable_channel, + V1_6::WifiUsableChannel* hidl_usable_channel) { + if (!hidl_usable_channel) { + return false; + } + *hidl_usable_channel = {}; + hidl_usable_channel->channel = legacy_usable_channel.freq; + hidl_usable_channel->channelBandwidth = + convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width); + hidl_usable_channel->ifaceModeMask = + convertLegacyWifiInterfaceModeToHidl(legacy_usable_channel.iface_mode_mask); + + return true; +} + +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector& legacy_usable_channels, + std::vector* hidl_usable_channels) { + if (!hidl_usable_channels) { + return false; + } + *hidl_usable_channels = {}; + for (const auto& legacy_usable_channel : legacy_usable_channels) { + V1_6::WifiUsableChannel hidl_usable_channel; + if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel, &hidl_usable_channel)) { + return false; + } + hidl_usable_channels->push_back(hidl_usable_channel); + } + return true; +} + +bool convertLegacyWifiMacInfosToHidl( + const std::vector& legacy_mac_infos, + std::vector* hidl_radio_mode_infos) { + if (!hidl_radio_mode_infos) { + return false; + } + *hidl_radio_mode_infos = {}; + + for (const auto& legacy_mac_info : legacy_mac_infos) { + V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; + if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) { + return false; + } + hidl_radio_mode_infos->push_back(hidl_radio_mode_info); + } + return true; +} + +bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature); + } + } + for (const auto feature : + {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS, WIFI_FEATURE_RSSI_MONITOR, + WIFI_FEATURE_CONTROL_ROAMING, WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND, + WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO, WIFI_FEATURE_TDLS, + WIFI_FEATURE_TDLS_OFFCHANNEL, WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature); + } + } + // There is no flag for this one in the legacy feature set. Adding it to the + // set because all the current devices support it. + *hidl_caps |= HidlStaIfaceCaps::APF; + return true; +} + +bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->version = legacy_caps.version; + hidl_caps->maxLength = legacy_caps.max_len; + return true; +} + +uint8_t convertHidlGscanReportEventFlagToLegacy( + StaBackgroundScanBucketEventReportSchemeMask hidl_flag) { + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + switch (hidl_flag) { + case HidlFlag::EACH_SCAN: + return REPORT_EVENTS_EACH_SCAN; + case HidlFlag::FULL_RESULTS: + return REPORT_EVENTS_FULL_RESULTS; + case HidlFlag::NO_BATCH: + return REPORT_EVENTS_NO_BATCH; + }; + CHECK(false); +} + +StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) { + switch (legacy_flag) { + case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED: + return StaScanDataFlagMask::INTERRUPTED; + }; + CHECK(false) << "Unknown legacy flag: " << legacy_flag; + // To silence the compiler warning about reaching the end of non-void + // function. + return {}; +} + +bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size; + hidl_caps->maxBuckets = legacy_caps.max_scan_buckets; + hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan; + hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold; + return true; +} + +legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band) { + switch (band) { + case V1_0::WifiBand::BAND_UNSPECIFIED: + return legacy_hal::WIFI_BAND_UNSPECIFIED; + case V1_0::WifiBand::BAND_24GHZ: + return legacy_hal::WIFI_BAND_BG; + case V1_0::WifiBand::BAND_5GHZ: + return legacy_hal::WIFI_BAND_A; + case V1_0::WifiBand::BAND_5GHZ_DFS: + return legacy_hal::WIFI_BAND_A_DFS; + case V1_0::WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_A_WITH_DFS; + case V1_0::WifiBand::BAND_24GHZ_5GHZ: + return legacy_hal::WIFI_BAND_ABG; + case V1_0::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_ABG_WITH_DFS; + }; + CHECK(false); +} + +bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params) { + if (!legacy_scan_params) { + return false; + } + *legacy_scan_params = {}; + legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs; + legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan; + legacy_scan_params->report_threshold_percent = hidl_scan_params.reportThresholdPercent; + legacy_scan_params->report_threshold_num_scans = hidl_scan_params.reportThresholdNumScans; + if (hidl_scan_params.buckets.size() > MAX_BUCKETS) { + return false; + } + legacy_scan_params->num_buckets = hidl_scan_params.buckets.size(); + for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); bucket_idx++) { + const StaBackgroundScanBucketParameters& hidl_bucket_spec = + hidl_scan_params.buckets[bucket_idx]; + legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec = + legacy_scan_params->buckets[bucket_idx]; + if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) { + return false; + } + legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx; + legacy_bucket_spec.band = convertHidlWifiBandToLegacy(hidl_bucket_spec.band); + legacy_bucket_spec.period = hidl_bucket_spec.periodInMs; + legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs; + legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase; + legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount; + legacy_bucket_spec.report_events = 0; + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) { + if (hidl_bucket_spec.eventReportScheme & + static_cast::type>(flag)) { + legacy_bucket_spec.report_events |= convertHidlGscanReportEventFlagToLegacy(flag); + } + } + if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) { + return false; + } + legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size(); + for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) { + legacy_bucket_spec.channels[freq_idx].channel = hidl_bucket_spec.frequencies[freq_idx]; + } + } + return true; +} + +bool convertLegacyIeToHidl(const legacy_hal::wifi_information_element& legacy_ie, + WifiInformationElement* hidl_ie) { + if (!hidl_ie) { + return false; + } + *hidl_ie = {}; + hidl_ie->id = legacy_ie.id; + hidl_ie->data = std::vector(legacy_ie.data, legacy_ie.data + legacy_ie.len); + return true; +} + +bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, uint32_t ie_blob_len, + std::vector* hidl_ies) { + if (!ie_blob || !hidl_ies) { + return false; + } + *hidl_ies = {}; + const uint8_t* ies_begin = ie_blob; + const uint8_t* ies_end = ie_blob + ie_blob_len; + const uint8_t* next_ie = ies_begin; + using wifi_ie = legacy_hal::wifi_information_element; + constexpr size_t kIeHeaderLen = sizeof(wifi_ie); + // Each IE should atleast have the header (i.e |id| & |len| fields). + while (next_ie + kIeHeaderLen <= ies_end) { + const wifi_ie& legacy_ie = (*reinterpret_cast(next_ie)); + uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len; + if (next_ie + curr_ie_len > ies_end) { + LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie + << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void*)ies_end; + break; + } + WifiInformationElement hidl_ie; + if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) { + LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id << ", len: " << legacy_ie.len; + break; + } + hidl_ies->push_back(std::move(hidl_ie)); + next_ie += curr_ie_len; + } + // Check if the blob has been fully consumed. + if (next_ie != ies_end) { + LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void*)next_ie + << ", IEs End: " << (void*)ies_end; + } + return true; +} + +bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result, + bool has_ie_data, StaScanResult* hidl_scan_result) { + if (!hidl_scan_result) { + return false; + } + *hidl_scan_result = {}; + hidl_scan_result->timeStampInUs = legacy_scan_result.ts; + hidl_scan_result->ssid = std::vector( + legacy_scan_result.ssid, + legacy_scan_result.ssid + + strnlen(legacy_scan_result.ssid, sizeof(legacy_scan_result.ssid) - 1)); + memcpy(hidl_scan_result->bssid.data(), legacy_scan_result.bssid, + hidl_scan_result->bssid.size()); + hidl_scan_result->frequency = legacy_scan_result.channel; + hidl_scan_result->rssi = legacy_scan_result.rssi; + hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period; + hidl_scan_result->capability = legacy_scan_result.capability; + if (has_ie_data) { + std::vector ies; + if (!convertLegacyIeBlobToHidl(reinterpret_cast(legacy_scan_result.ie_data), + legacy_scan_result.ie_length, &ies)) { + return false; + } + hidl_scan_result->informationElements = std::move(ies); + } + return true; +} + +bool convertLegacyCachedGscanResultsToHidl( + const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result, + StaScanData* hidl_scan_data) { + if (!hidl_scan_data) { + return false; + } + *hidl_scan_data = {}; + hidl_scan_data->flags = 0; + for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) { + if (legacy_cached_scan_result.flags & flag) { + hidl_scan_data->flags |= static_cast::type>( + convertLegacyGscanDataFlagToHidl(flag)); + } + } + hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned; + + CHECK(legacy_cached_scan_result.num_results >= 0 && + legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN); + std::vector hidl_scan_results; + for (int32_t result_idx = 0; result_idx < legacy_cached_scan_result.num_results; result_idx++) { + StaScanResult hidl_scan_result; + if (!convertLegacyGscanResultToHidl(legacy_cached_scan_result.results[result_idx], false, + &hidl_scan_result)) { + return false; + } + hidl_scan_results.push_back(hidl_scan_result); + } + hidl_scan_data->results = std::move(hidl_scan_results); + return true; +} + +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector& legacy_cached_scan_results, + std::vector* hidl_scan_datas) { + if (!hidl_scan_datas) { + return false; + } + *hidl_scan_datas = {}; + for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) { + StaScanData hidl_scan_data; + if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result, &hidl_scan_data)) { + return false; + } + hidl_scan_datas->push_back(hidl_scan_data); + } + return true; +} + +WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(legacy_hal::wifi_tx_packet_fate fate) { + switch (fate) { + case legacy_hal::TX_PKT_FATE_ACKED: + return WifiDebugTxPacketFate::ACKED; + case legacy_hal::TX_PKT_FATE_SENT: + return WifiDebugTxPacketFate::SENT; + case legacy_hal::TX_PKT_FATE_FW_QUEUED: + return WifiDebugTxPacketFate::FW_QUEUED; + case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugTxPacketFate::FW_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugTxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugTxPacketFate::FW_DROP_OTHER; + case legacy_hal::TX_PKT_FATE_DRV_QUEUED: + return WifiDebugTxPacketFate::DRV_QUEUED; + case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugTxPacketFate::DRV_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugTxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugTxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(legacy_hal::wifi_rx_packet_fate fate) { + switch (fate) { + case legacy_hal::RX_PKT_FATE_SUCCESS: + return WifiDebugRxPacketFate::SUCCESS; + case legacy_hal::RX_PKT_FATE_FW_QUEUED: + return WifiDebugRxPacketFate::FW_QUEUED; + case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER: + return WifiDebugRxPacketFate::FW_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugRxPacketFate::FW_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugRxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugRxPacketFate::FW_DROP_OTHER; + case legacy_hal::RX_PKT_FATE_DRV_QUEUED: + return WifiDebugRxPacketFate::DRV_QUEUED; + case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER: + return WifiDebugRxPacketFate::DRV_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugRxPacketFate::DRV_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugRxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugRxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl( + legacy_hal::frame_type type) { + switch (type) { + case legacy_hal::FRAME_TYPE_UNKNOWN: + return WifiDebugPacketFateFrameType::UNKNOWN; + case legacy_hal::FRAME_TYPE_ETHERNET_II: + return WifiDebugPacketFateFrameType::ETHERNET_II; + case legacy_hal::FRAME_TYPE_80211_MGMT: + return WifiDebugPacketFateFrameType::MGMT_80211; + }; + CHECK(false) << "Unknown legacy frame type: " << type; +} + +bool convertLegacyDebugPacketFateFrameToHidl(const legacy_hal::frame_info& legacy_frame, + WifiDebugPacketFateFrameInfo* hidl_frame) { + if (!hidl_frame) { + return false; + } + *hidl_frame = {}; + hidl_frame->frameType = convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type); + hidl_frame->frameLen = legacy_frame.frame_len; + hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec; + hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec; + const uint8_t* frame_begin = + reinterpret_cast(legacy_frame.frame_content.ethernet_ii_bytes); + hidl_frame->frameContent = + std::vector(frame_begin, frame_begin + legacy_frame.frame_len); + return true; +} + +bool convertLegacyDebugTxPacketFateToHidl(const legacy_hal::wifi_tx_report& legacy_fate, + WifiDebugTxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugTxPacketFateReport hidl_fate; + if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyDebugRxPacketFateToHidl(const legacy_hal::wifi_rx_report& legacy_fate, + WifiDebugRxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugRxPacketFateReport hidl_fate; + if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyLinkLayerRadioStatsToHidl( + const legacy_hal::LinkLayerRadioStats& legacy_radio_stat, + V1_6::StaLinkLayerRadioStats* hidl_radio_stat) { + if (!hidl_radio_stat) { + return false; + } + *hidl_radio_stat = {}; + + hidl_radio_stat->radioId = legacy_radio_stat.stats.radio; + hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time; + hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time; + hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time; + hidl_radio_stat->V1_0.onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan; + hidl_radio_stat->V1_0.txTimeInMsPerLevel = legacy_radio_stat.tx_time_per_levels; + hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd; + hidl_radio_stat->onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan; + hidl_radio_stat->onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan; + hidl_radio_stat->onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan; + hidl_radio_stat->onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20; + + std::vector hidl_channel_stats; + + for (const auto& channel_stat : legacy_radio_stat.channel_stats) { + V1_6::WifiChannelStats hidl_channel_stat; + hidl_channel_stat.onTimeInMs = channel_stat.on_time; + hidl_channel_stat.ccaBusyTimeInMs = channel_stat.cca_busy_time; + /* + * TODO once b/119142899 is fixed, + * replace below code with convertLegacyWifiChannelInfoToHidl() + */ + hidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20; + hidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq; + hidl_channel_stat.channel.centerFreq0 = channel_stat.channel.center_freq0; + hidl_channel_stat.channel.centerFreq1 = channel_stat.channel.center_freq1; + hidl_channel_stats.push_back(hidl_channel_stat); + } + + hidl_radio_stat->channelStats = hidl_channel_stats; + + return true; +} + +bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats, + V1_6::StaLinkLayerStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + // iface legacy_stats conversion. + hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx; + hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + hidl_stats->iface.V1_0.wmeBePktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + hidl_stats->iface.V1_0.wmeBePktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max; + hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg; + hidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples; + hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + hidl_stats->iface.V1_0.wmeBkPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max; + hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg; + hidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples; + hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + hidl_stats->iface.V1_0.wmeViPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + hidl_stats->iface.V1_0.wmeViPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max; + hidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg; + hidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples; + hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + hidl_stats->iface.V1_0.wmeVoPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max; + hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg; + hidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples; + hidl_stats->iface.timeSliceDutyCycleInPercent = + legacy_stats.iface.info.time_slicing_duty_cycle_percent; + // peer info legacy_stats conversion. + std::vector hidl_peers_info_stats; + for (const auto& legacy_peer_info_stats : legacy_stats.peers) { + V1_6::StaPeerInfo hidl_peer_info_stats; + if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats, &hidl_peer_info_stats)) { + return false; + } + hidl_peers_info_stats.push_back(hidl_peer_info_stats); + } + hidl_stats->iface.peers = hidl_peers_info_stats; + // radio legacy_stats conversion. + std::vector hidl_radios_stats; + for (const auto& legacy_radio_stats : legacy_stats.radios) { + V1_6::StaLinkLayerRadioStats hidl_radio_stats; + if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, &hidl_radio_stats)) { + return false; + } + hidl_radios_stats.push_back(hidl_radio_stats); + } + hidl_stats->radios = hidl_radios_stats; + // Timestamp in the HAL wrapper here since it's not provided in the legacy + // HAL API. + hidl_stats->timeStampInMs = uptimeMillis(); + return true; +} + +bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + V1_6::StaPeerInfo* hidl_peer_info_stats) { + if (!hidl_peer_info_stats) { + return false; + } + *hidl_peer_info_stats = {}; + hidl_peer_info_stats->staCount = legacy_peer_info_stats.peer_info.bssload.sta_count; + hidl_peer_info_stats->chanUtil = legacy_peer_info_stats.peer_info.bssload.chan_util; + + std::vector hidlRateStats; + for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) { + V1_6::StaRateStat rateStat; + if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate, &rateStat.rateInfo)) { + return false; + } + rateStat.txMpdu = legacy_rate_stats.tx_mpdu; + rateStat.rxMpdu = legacy_rate_stats.rx_mpdu; + rateStat.mpduLost = legacy_rate_stats.mpdu_lost; + rateStat.retries = legacy_rate_stats.retries; + hidlRateStats.push_back(rateStat); + } + hidl_peer_info_stats->rateStats = hidlRateStats; + return true; +} + +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size; + hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size; + return true; +} + +bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID || + hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) { + return false; + } + legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size(); + uint32_t i = 0; + for (const auto& bssid : hidl_config.bssidBlacklist) { + CHECK(bssid.size() == sizeof(legacy_hal::mac_addr)); + memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size()); + } + legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size(); + i = 0; + for (const auto& ssid : hidl_config.ssidWhitelist) { + CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str)); + legacy_config->whitelist_ssid[i].length = ssid.size(); + memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), ssid.size()); + i++; + } + return true; +} + +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state) { + switch (state) { + case StaRoamingState::ENABLED: + return legacy_hal::ROAMING_ENABLE; + case StaRoamingState::DISABLED: + return legacy_hal::ROAMING_DISABLE; + }; + CHECK(false); +} + +legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) { + switch (type) { + case NanMatchAlg::MATCH_ONCE: + return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE; + case NanMatchAlg::MATCH_CONTINUOUS: + return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS; + case NanMatchAlg::MATCH_NEVER: + return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER; + } + CHECK(false); +} + +legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(NanPublishType type) { + switch (type) { + case NanPublishType::UNSOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED; + case NanPublishType::SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED; + case NanPublishType::UNSOLICITED_SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED; + } + CHECK(false); +} + +legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) { + switch (type) { + case NanTxType::BROADCAST: + return legacy_hal::NAN_TX_TYPE_BROADCAST; + case NanTxType::UNICAST: + return legacy_hal::NAN_TX_TYPE_UNICAST; + } + CHECK(false); +} + +legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(NanSubscribeType type) { + switch (type) { + case NanSubscribeType::PASSIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE; + case NanSubscribeType::ACTIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE; + } + CHECK(false); +} + +legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) { + switch (type) { + case NanSrfType::BLOOM_FILTER: + return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER; + case NanSrfType::PARTIAL_MAC_ADDR: + return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR; + } + CHECK(false); +} + +legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy( + NanDataPathChannelCfg type) { + switch (type) { + case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED: + return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED; + case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP: + return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP; + case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP: + return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP; + } + CHECK(false); +} + +NanStatusType convertLegacyNanStatusTypeToHidl(legacy_hal::NanStatusType type) { + switch (type) { + case legacy_hal::NAN_STATUS_SUCCESS: + return NanStatusType::SUCCESS; + case legacy_hal::NAN_STATUS_INTERNAL_FAILURE: + return NanStatusType::INTERNAL_FAILURE; + case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE: + return NanStatusType::PROTOCOL_FAILURE; + case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID: + return NanStatusType::INVALID_SESSION_ID; + case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE: + return NanStatusType::NO_RESOURCES_AVAILABLE; + case legacy_hal::NAN_STATUS_INVALID_PARAM: + return NanStatusType::INVALID_ARGS; + case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID: + return NanStatusType::INVALID_PEER_ID; + case legacy_hal::NAN_STATUS_INVALID_NDP_ID: + return NanStatusType::INVALID_NDP_ID; + case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED: + return NanStatusType::NAN_NOT_ALLOWED; + case legacy_hal::NAN_STATUS_NO_OTA_ACK: + return NanStatusType::NO_OTA_ACK; + case legacy_hal::NAN_STATUS_ALREADY_ENABLED: + return NanStatusType::ALREADY_ENABLED; + case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL: + return NanStatusType::FOLLOWUP_TX_QUEUE_FULL; + case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED; + } + CHECK(false); +} + +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, + WifiNanStatus* wifiNanStatus) { + wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type); + wifiNanStatus->description = safeConvertChar(str, max_len); +} + +bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->config_2dot4g_support = 1; + legacy_request->support_2dot4g_val = + hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_support_5g = 1; + legacy_request->support_5g_val = + hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_hop_count_limit = 1; + legacy_request->hop_count_limit_val = hidl_request.hopCountMax; + legacy_request->master_pref = hidl_request.configParams.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon_val = + (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = hidl_request.configParams.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.configParams.macAddressRandomizationIntervalSec; + legacy_request->config_2dot4g_rssi_close = 1; + if (hidl_request.configParams.bandSpecificConfig.size() != 3) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "bandSpecificConfig.size() != 3"; + return false; + } + legacy_request->rssi_close_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiCloseProximity; + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .discoveryWindowIntervalVal; + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiMiddle; + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiCloseProximity; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = + hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .discoveryWindowIntervalVal; + if (hidl_request.debugConfigs.validClusterIdVals) { + legacy_request->cluster_low = hidl_request.debugConfigs.clusterIdBottomRangeVal; + legacy_request->cluster_high = hidl_request.debugConfigs.clusterIdTopRangeVal; + } else { // need 'else' since not configurable in legacy HAL + legacy_request->cluster_low = 0x0000; + legacy_request->cluster_high = 0xFFFF; + } + legacy_request->config_intf_addr = hidl_request.debugConfigs.validIntfAddrVal; + memcpy(legacy_request->intf_addr_val, hidl_request.debugConfigs.intfAddrVal.data(), 6); + legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal; + legacy_request->oui_val = hidl_request.debugConfigs.ouiVal; + legacy_request->config_random_factor_force = + hidl_request.debugConfigs.validRandomFactorForceVal; + legacy_request->random_factor_force_val = hidl_request.debugConfigs.randomFactorForceVal; + legacy_request->config_hop_count_force = hidl_request.debugConfigs.validHopCountForceVal; + legacy_request->hop_count_force_val = hidl_request.debugConfigs.hopCountForceVal; + legacy_request->config_24g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_24g_val = + hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_5g_val = + hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_2dot4g_val = + hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_5g_val = + hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_2dot4g_val = + hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_5g_val = + hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + + /* TODO: b/145609058 + * Missing updates needed to legacy_hal::NanEnableRequest and conversion to + * it for 6GHz band */ + + return true; +} + +bool convertHidlNanEnableRequest_1_6ToLegacy(const V1_4::NanEnableRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanEnableRequest_1_6ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging; + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode; + legacy_request->config_instant_mode_channel = 1; + legacy_request->instant_mode_channel = hidl_request2.instantModeChannel; + + return true; +} + +bool convertHidlNanConfigRequest_1_6ToLegacy(const V1_4::NanConfigRequest& hidl_request1, + const NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanConfigRequest_1_6ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging; + + legacy_request->config_enable_instant_mode = 1; + legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode; + legacy_request->config_instant_mode_channel = 1; + legacy_request->instant_mode_channel = hidl_request2.instantModeChannel; + + return true; +} + +bool convertHidlNanPublishRequestToLegacy(const V1_6::NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len " + "too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->publish_match_indicator = + convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->recv_indication_cfg |= 0x8; + legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType; + + legacy_request->scid_len = hidl_request.baseConfigs.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.baseConfigs.securityConfig.scid.data(), + legacy_request->scid_len); + + if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = + (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + + legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_ENABLE + : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = + hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10; + legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE + : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->publish_type = convertHidlNanPublishTypeToLegacy(hidl_request.publishType); + legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType); + legacy_request->service_responder_policy = hidl_request.autoAcceptDataPathRequests + ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL + : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE; + + return true; +} + +bool convertHidlNanSubscribeRequestToLegacy(const V1_0::NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->subscribe_match_indicator = + convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType; + if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = + (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_ENABLE + : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = + hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10; + legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE + : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->subscribe_type = + convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType); + legacy_request->serviceResponseFilter = convertHidlNanSrfTypeToLegacy(hidl_request.srfType); + legacy_request->serviceResponseInclude = hidl_request.srfRespondIfInAddressSet + ? legacy_hal::NAN_SRF_INCLUDE_RESPOND + : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND; + legacy_request->useServiceResponseFilter = + hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF; + legacy_request->ssiRequiredForMatchIndication = + hidl_request.isSsiRequiredForMatch ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND + : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; + legacy_request->num_intf_addr_present = hidl_request.intfAddr.size(); + if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "num_intf_addr_present - too many"; + return false; + } + for (int i = 0; i < legacy_request->num_intf_addr_present; i++) { + memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), 6); + } + + return true; +} + +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_subscribe_id = hidl_request.discoverySessionId; + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->addr, hidl_request.addr.data(), 6); + legacy_request->priority = hidl_request.isHighPriority ? legacy_hal::NAN_TX_PRIORITY_HIGH + : legacy_hal::NAN_TX_PRIORITY_NORMAL; + legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow + ? legacy_hal::NAN_TRANSMIT_IN_DW + : legacy_hal::NAN_TRANSMIT_IN_FAW; + legacy_request->service_specific_info_len = hidl_request.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, hidl_request.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->recv_indication_cfg = hidl_request.disableFollowupResultIndication ? 0x1 : 0x0; + + return true; +} + +bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown + // defaults + legacy_request->master_pref = hidl_request.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: " + "numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon = (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: " + "numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.macAddressRandomizationIntervalSec; + /* TODO : missing + legacy_request->config_2dot4g_rssi_close = 1; + legacy_request->rssi_close_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity; + */ + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .discoveryWindowIntervalVal; + /* TODO: missing + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle; + */ + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs; + legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .discoveryWindowIntervalVal; + /* TODO: b/145609058 + * Missing updates needed to legacy_hal::NanConfigRequest and conversion to + * it for 6GHz band */ + + return true; +} + +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const V1_0::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6); + legacy_request->channel_request_type = + convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType); + legacy_request->channel = hidl_request.channel; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertHidlNanDataPathInitiatorRequest_1_6ToLegacy( + const V1_6::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6); + legacy_request->channel_request_type = + convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType); + legacy_request->channel = hidl_request.channel; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + legacy_request->scid_len = hidl_request.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_len); + + return true; +} + +bool convertHidlNanDataPathIndicationResponseToLegacy( + const V1_0::NanRespondToDataPathIndicationRequest& hidl_request, + legacy_hal::NanDataPathIndicationResponse* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->rsp_code = hidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT + : legacy_hal::NAN_DP_REQUEST_REJECT; + legacy_request->ndp_instance_id = hidl_request.ndpInstanceId; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertHidlNanDataPathIndicationResponse_1_6ToLegacy( + const V1_6::NanRespondToDataPathIndicationRequest& hidl_request, + legacy_hal::NanDataPathIndicationResponse* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->rsp_code = hidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT + : legacy_hal::NAN_DP_REQUEST_REJECT; + legacy_request->ndp_instance_id = hidl_request.ndpInstanceId; + if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "ifaceName too long"; + return false; + } + strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + legacy_request->scid_len = hidl_request.securityConfig.scid.size(); + if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: scid_len too large"; + return false; + } + memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_len); + + return true; +} + +bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus) { + if (!wifiNanStatus) { + LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null"; + return false; + } + *wifiNanStatus = {}; + + convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error, + sizeof(legacy_response.nan_error), wifiNanStatus); + return true; +} + +bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response, + V1_6::NanCapabilities* hidl_response) { + if (!hidl_response) { + LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: " + "hidl_response is null"; + return false; + } + *hidl_response = {}; + + hidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters; + hidl_response->maxPublishes = legacy_response.max_publishes; + hidl_response->maxSubscribes = legacy_response.max_subscribes; + hidl_response->maxServiceNameLen = legacy_response.max_service_name_len; + hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len; + hidl_response->maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len; + hidl_response->maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len; + hidl_response->maxExtendedServiceSpecificInfoLen = + legacy_response.max_sdea_service_specific_info_len; + hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces; + hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions; + hidl_response->maxAppInfoLen = legacy_response.max_app_info_len; + hidl_response->maxQueuedTransmitFollowupMsgs = + legacy_response.max_queued_transmit_followup_msgs; + hidl_response->maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address; + hidl_response->supportedCipherSuites = legacy_response.cipher_suites_supported; + hidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported; + + return true; +} + +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + V1_6::NanMatchInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array(legacy_ind.addr); + hidl_ind->serviceSpecificInfo = std::vector( + legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector( + legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len); + hidl_ind->matchFilter = + std::vector(legacy_ind.sdf_match_filter, + legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len); + hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1; + hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1; + hidl_ind->rssiValue = legacy_ind.rssi_value; + hidl_ind->peerCipherType = (V1_6::NanCipherSuiteType)legacy_ind.peer_cipher_type; + hidl_ind->peerRequiresSecurityEnabledInNdp = + legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->peerRequiresRanging = + legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE; + hidl_ind->rangingMeasurementInMm = legacy_ind.range_info.range_measurement_mm; + hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type; + hidl_ind->scid = std::vector(legacy_ind.scid, legacy_ind.scid + legacy_ind.scid_len); + return true; +} + +bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind, + NanFollowupReceivedInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array(legacy_ind.addr); + hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1; + hidl_ind->serviceSpecificInfo = std::vector( + legacy_ind.service_specific_info, + legacy_ind.service_specific_info + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = std::vector( + legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len); + + return true; +} + +bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.service_instance_id; + hidl_ind->peerDiscMacAddr = hidl_array(legacy_ind.peer_disc_mac_addr); + hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->securityRequired = + legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->appInfo = std::vector( + legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len); + + return true; +} + +bool convertLegacyNdpChannelInfoToHidl(const legacy_hal::NanChannelInfo& legacy_struct, + V1_6::NanDataPathChannelInfo* hidl_struct) { + if (!hidl_struct) { + LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null"; + return false; + } + *hidl_struct = {}; + + hidl_struct->channelFreq = legacy_struct.channel; + hidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToHidl( + (legacy_hal::wifi_channel_width)legacy_struct.bandwidth); + hidl_struct->numSpatialStreams = legacy_struct.nss; + + return true; +} + +bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind, + V1_6::NanDataPathConfirmInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->V1_0.dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT; + hidl_ind->V1_0.peerNdiMacAddr = hidl_array(legacy_ind.peer_ndi_mac_addr); + hidl_ind->V1_0.appInfo = std::vector( + legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len); + hidl_ind->V1_0.status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code); + hidl_ind->V1_0.status.description = ""; // TODO: b/34059183 + + std::vector channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_6::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + + return true; +} + +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_6::NanDataPathScheduleUpdateInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: " + "hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->peerDiscoveryAddress = hidl_array(legacy_ind.peer_mac_addr); + std::vector channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_6::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + std::vector ndpInstanceIds; + for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) { + ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]); + } + hidl_ind->ndpInstanceIds = ndpInstanceIds; + + return true; +} + +legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) { + switch (type) { + case RttType::ONE_SIDED: + return legacy_hal::RTT_TYPE_1_SIDED; + case RttType::TWO_SIDED: + return legacy_hal::RTT_TYPE_2_SIDED; + }; + CHECK(false); +} + +RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) { + switch (type) { + case legacy_hal::RTT_TYPE_1_SIDED: + return RttType::ONE_SIDED; + case legacy_hal::RTT_TYPE_2_SIDED: + return RttType::TWO_SIDED; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) { + switch (type) { + case RttPeerType::AP: + return legacy_hal::RTT_PEER_AP; + case RttPeerType::STA: + return legacy_hal::RTT_PEER_STA; + case RttPeerType::P2P_GO: + return legacy_hal::RTT_PEER_P2P_GO; + case RttPeerType::P2P_CLIENT: + return legacy_hal::RTT_PEER_P2P_CLIENT; + case RttPeerType::NAN: + return legacy_hal::RTT_PEER_NAN; + }; + CHECK(false); +} + +legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(WifiChannelWidthInMhz type) { + switch (type) { + case WifiChannelWidthInMhz::WIDTH_20: + return legacy_hal::WIFI_CHAN_WIDTH_20; + case WifiChannelWidthInMhz::WIDTH_40: + return legacy_hal::WIFI_CHAN_WIDTH_40; + case WifiChannelWidthInMhz::WIDTH_80: + return legacy_hal::WIFI_CHAN_WIDTH_80; + case WifiChannelWidthInMhz::WIDTH_160: + return legacy_hal::WIFI_CHAN_WIDTH_160; + case WifiChannelWidthInMhz::WIDTH_80P80: + return legacy_hal::WIFI_CHAN_WIDTH_80P80; + case WifiChannelWidthInMhz::WIDTH_5: + return legacy_hal::WIFI_CHAN_WIDTH_5; + case WifiChannelWidthInMhz::WIDTH_10: + return legacy_hal::WIFI_CHAN_WIDTH_10; + case V1_6::WifiChannelWidthInMhz::WIDTH_320: + return legacy_hal::WIFI_CHAN_WIDTH_320; + case WifiChannelWidthInMhz::WIDTH_INVALID: + return legacy_hal::WIFI_CHAN_WIDTH_INVALID; + }; + CHECK(false); +} + +V1_6::WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl( + legacy_hal::wifi_channel_width type) { + switch (type) { + case legacy_hal::WIFI_CHAN_WIDTH_20: + return WifiChannelWidthInMhz::WIDTH_20; + case legacy_hal::WIFI_CHAN_WIDTH_40: + return WifiChannelWidthInMhz::WIDTH_40; + case legacy_hal::WIFI_CHAN_WIDTH_80: + return WifiChannelWidthInMhz::WIDTH_80; + case legacy_hal::WIFI_CHAN_WIDTH_160: + return WifiChannelWidthInMhz::WIDTH_160; + case legacy_hal::WIFI_CHAN_WIDTH_80P80: + return WifiChannelWidthInMhz::WIDTH_80P80; + case legacy_hal::WIFI_CHAN_WIDTH_5: + return WifiChannelWidthInMhz::WIDTH_5; + case legacy_hal::WIFI_CHAN_WIDTH_10: + return WifiChannelWidthInMhz::WIDTH_10; + case legacy_hal::WIFI_CHAN_WIDTH_320: + return V1_6::WifiChannelWidthInMhz::WIDTH_320; + default: + return WifiChannelWidthInMhz::WIDTH_INVALID; + }; +} + +legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(V1_6::RttPreamble type) { + switch (type) { + case V1_6::RttPreamble::LEGACY: + return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY; + case V1_6::RttPreamble::HT: + return legacy_hal::WIFI_RTT_PREAMBLE_HT; + case V1_6::RttPreamble::VHT: + return legacy_hal::WIFI_RTT_PREAMBLE_VHT; + case V1_6::RttPreamble::HE: + return legacy_hal::WIFI_RTT_PREAMBLE_HE; + case V1_6::RttPreamble::EHT: + return legacy_hal::WIFI_RTT_PREAMBLE_EHT; + }; + CHECK(false); +} + +V1_6::RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) { + switch (type) { + case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY: + return V1_6::RttPreamble::LEGACY; + case legacy_hal::WIFI_RTT_PREAMBLE_HT: + return V1_6::RttPreamble::HT; + case legacy_hal::WIFI_RTT_PREAMBLE_VHT: + return V1_6::RttPreamble::VHT; + case legacy_hal::WIFI_RTT_PREAMBLE_HE: + return V1_6::RttPreamble::HE; + case legacy_hal::WIFI_RTT_PREAMBLE_EHT: + return V1_6::RttPreamble::EHT; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) { + switch (type) { + case RttBw::BW_5MHZ: + return legacy_hal::WIFI_RTT_BW_5; + case RttBw::BW_10MHZ: + return legacy_hal::WIFI_RTT_BW_10; + case RttBw::BW_20MHZ: + return legacy_hal::WIFI_RTT_BW_20; + case RttBw::BW_40MHZ: + return legacy_hal::WIFI_RTT_BW_40; + case RttBw::BW_80MHZ: + return legacy_hal::WIFI_RTT_BW_80; + case RttBw::BW_160MHZ: + return legacy_hal::WIFI_RTT_BW_160; + case RttBw::BW_320MHZ: + return legacy_hal::WIFI_RTT_BW_320; + }; + CHECK(false); +} + +RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) { + switch (type) { + case legacy_hal::WIFI_RTT_BW_5: + return RttBw::BW_5MHZ; + case legacy_hal::WIFI_RTT_BW_10: + return RttBw::BW_10MHZ; + case legacy_hal::WIFI_RTT_BW_20: + return RttBw::BW_20MHZ; + case legacy_hal::WIFI_RTT_BW_40: + return RttBw::BW_40MHZ; + case legacy_hal::WIFI_RTT_BW_80: + return RttBw::BW_80MHZ; + case legacy_hal::WIFI_RTT_BW_160: + return RttBw::BW_160MHZ; + case legacy_hal::WIFI_RTT_BW_320: + return RttBw::BW_320MHZ; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(RttMotionPattern type) { + switch (type) { + case RttMotionPattern::NOT_EXPECTED: + return legacy_hal::WIFI_MOTION_NOT_EXPECTED; + case RttMotionPattern::EXPECTED: + return legacy_hal::WIFI_MOTION_EXPECTED; + case RttMotionPattern::UNKNOWN: + return legacy_hal::WIFI_MOTION_UNKNOWN; + }; + CHECK(false); +} + +V1_6::WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { + switch (preamble) { + case 0: + return V1_6::WifiRatePreamble::OFDM; + case 1: + return V1_6::WifiRatePreamble::CCK; + case 2: + return V1_6::WifiRatePreamble::HT; + case 3: + return V1_6::WifiRatePreamble::VHT; + case 4: + return V1_6::WifiRatePreamble::HE; + case 5: + return V1_6::WifiRatePreamble::EHT; + default: + return V1_6::WifiRatePreamble::RESERVED; + }; + CHECK(false) << "Unknown legacy preamble: " << preamble; +} + +WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) { + switch (nss) { + case 0: + return WifiRateNss::NSS_1x1; + case 1: + return WifiRateNss::NSS_2x2; + case 2: + return WifiRateNss::NSS_3x3; + case 3: + return WifiRateNss::NSS_4x4; + }; + CHECK(false) << "Unknown legacy nss: " << nss; + return {}; +} + +RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) { + switch (status) { + case legacy_hal::RTT_STATUS_SUCCESS: + return RttStatus::SUCCESS; + case legacy_hal::RTT_STATUS_FAILURE: + return RttStatus::FAILURE; + case legacy_hal::RTT_STATUS_FAIL_NO_RSP: + return RttStatus::FAIL_NO_RSP; + case legacy_hal::RTT_STATUS_FAIL_REJECTED: + return RttStatus::FAIL_REJECTED; + case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET: + return RttStatus::FAIL_NOT_SCHEDULED_YET; + case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT: + return RttStatus::FAIL_TM_TIMEOUT; + case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: + return RttStatus::FAIL_AP_ON_DIFF_CHANNEL; + case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY: + return RttStatus::FAIL_NO_CAPABILITY; + case legacy_hal::RTT_STATUS_ABORTED: + return RttStatus::ABORTED; + case legacy_hal::RTT_STATUS_FAIL_INVALID_TS: + return RttStatus::FAIL_INVALID_TS; + case legacy_hal::RTT_STATUS_FAIL_PROTOCOL: + return RttStatus::FAIL_PROTOCOL; + case legacy_hal::RTT_STATUS_FAIL_SCHEDULE: + return RttStatus::FAIL_SCHEDULE; + case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER: + return RttStatus::FAIL_BUSY_TRY_LATER; + case legacy_hal::RTT_STATUS_INVALID_REQ: + return RttStatus::INVALID_REQ; + case legacy_hal::RTT_STATUS_NO_WIFI: + return RttStatus::NO_WIFI; + case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: + return RttStatus::FAIL_FTM_PARAM_OVERRIDE; + case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + }; + CHECK(false) << "Unknown legacy status: " << status; +} + +bool convertHidlWifiChannelInfoToLegacy(const WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width); + legacy_info->center_freq = hidl_info.centerFreq; + legacy_info->center_freq0 = hidl_info.centerFreq0; + legacy_info->center_freq1 = hidl_info.centerFreq1; + return true; +} + +bool convertLegacyWifiChannelInfoToHidl(const legacy_hal::wifi_channel_info& legacy_info, + WifiChannelInfo* hidl_info) { + if (!hidl_info) { + return false; + } + *hidl_info = {}; + hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width); + hidl_info->centerFreq = legacy_info.center_freq; + hidl_info->centerFreq0 = legacy_info.center_freq0; + hidl_info->centerFreq1 = legacy_info.center_freq1; + return true; +} + +bool convertHidlRttConfigToLegacy(const V1_6::RttConfig& hidl_config, + legacy_hal::wifi_rtt_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr)); + memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size()); + legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type); + legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer); + if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel, &legacy_config->channel)) { + return false; + } + legacy_config->burst_period = hidl_config.burstPeriod; + legacy_config->num_burst = hidl_config.numBurst; + legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst; + legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame; + legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr; + legacy_config->LCI_request = hidl_config.mustRequestLci; + legacy_config->LCR_request = hidl_config.mustRequestLcr; + legacy_config->burst_duration = hidl_config.burstDuration; + legacy_config->preamble = convertHidlRttPreambleToLegacy(hidl_config.preamble); + legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw); + return true; +} + +bool convertHidlVectorOfRttConfigToLegacy( + const std::vector& hidl_configs, + std::vector* legacy_configs) { + if (!legacy_configs) { + return false; + } + *legacy_configs = {}; + for (const auto& hidl_config : hidl_configs) { + legacy_hal::wifi_rtt_config legacy_config; + if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) { + return false; + } + legacy_configs->push_back(legacy_config); + } + return true; +} + +bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->latitude = hidl_info.latitude; + legacy_info->longitude = hidl_info.longitude; + legacy_info->altitude = hidl_info.altitude; + legacy_info->latitude_unc = hidl_info.latitudeUnc; + legacy_info->longitude_unc = hidl_info.longitudeUnc; + legacy_info->altitude_unc = hidl_info.altitudeUnc; + legacy_info->motion_pattern = convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern); + legacy_info->floor = hidl_info.floor; + legacy_info->height_above_floor = hidl_info.heightAboveFloor; + legacy_info->height_unc = hidl_info.heightUnc; + return true; +} + +bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code)); + memcpy(legacy_info->country_code, hidl_info.countryCode.data(), hidl_info.countryCode.size()); + if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) { + return false; + } + legacy_info->length = hidl_info.civicInfo.size(); + memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(), hidl_info.civicInfo.size()); + return true; +} + +bool convertHidlRttResponderToLegacy(const V1_6::RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder) { + if (!legacy_responder) { + return false; + } + *legacy_responder = {}; + if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel, &legacy_responder->channel)) { + return false; + } + legacy_responder->preamble = convertHidlRttPreambleToLegacy(hidl_responder.preamble); + return true; +} + +bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder, + V1_6::RttResponder* hidl_responder) { + if (!hidl_responder) { + return false; + } + *hidl_responder = {}; + if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel, &hidl_responder->channel)) { + return false; + } + hidl_responder->preamble = convertLegacyRttPreambleToHidl(legacy_responder.preamble); + return true; +} + +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + V1_6::RttCapabilities* hidl_capabilities) { + if (!hidl_capabilities) { + return false; + } + *hidl_capabilities = {}; + hidl_capabilities->rttOneSidedSupported = legacy_capabilities.rtt_one_sided_supported; + hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported; + hidl_capabilities->lciSupported = legacy_capabilities.lci_support; + hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support; + hidl_capabilities->responderSupported = legacy_capabilities.responder_supported; + hidl_capabilities->preambleSupport = 0; + for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT, + legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE, + legacy_hal::WIFI_RTT_PREAMBLE_EHT}) { + if (legacy_capabilities.preamble_support & flag) { + hidl_capabilities->preambleSupport |= + static_cast::type>( + convertLegacyRttPreambleToHidl(flag)); + } + } + hidl_capabilities->bwSupport = 0; + for (const auto flag : + {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10, legacy_hal::WIFI_RTT_BW_20, + legacy_hal::WIFI_RTT_BW_40, legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160, + legacy_hal::WIFI_RTT_BW_320}) { + if (legacy_capabilities.bw_support & flag) { + hidl_capabilities->bwSupport |= + static_cast::type>(convertLegacyRttBwToHidl(flag)); + } + } + hidl_capabilities->mcVersion = legacy_capabilities.mc_version; + return true; +} + +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + V1_6::WifiRateInfo* hidl_rate) { + if (!hidl_rate) { + return false; + } + *hidl_rate = {}; + hidl_rate->preamble = convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble); + hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss); + hidl_rate->bw = convertLegacyWifiChannelWidthToHidl( + static_cast(legacy_rate.bw)); + hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx; + hidl_rate->bitRateInKbps = legacy_rate.bitrate; + return true; +} + +bool convertLegacyRttResultToHidl(const legacy_hal::wifi_rtt_result& legacy_result, + V1_6::RttResult* hidl_result) { + if (!hidl_result) { + return false; + } + *hidl_result = {}; + CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size()); + memcpy(hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr)); + hidl_result->burstNum = legacy_result.burst_num; + hidl_result->measurementNumber = legacy_result.measurement_number; + hidl_result->successNumber = legacy_result.success_number; + hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer; + hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status); + hidl_result->retryAfterDuration = legacy_result.retry_after_duration; + hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type); + hidl_result->rssi = legacy_result.rssi; + hidl_result->rssiSpread = legacy_result.rssi_spread; + if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate, &hidl_result->txRate)) { + return false; + } + if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate, &hidl_result->rxRate)) { + return false; + } + hidl_result->rtt = legacy_result.rtt; + hidl_result->rttSd = legacy_result.rtt_sd; + hidl_result->rttSpread = legacy_result.rtt_spread; + hidl_result->distanceInMm = legacy_result.distance_mm; + hidl_result->distanceSdInMm = legacy_result.distance_sd_mm; + hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm; + hidl_result->timeStampInUs = legacy_result.ts; + hidl_result->burstDurationInMs = legacy_result.burst_duration; + hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num; + if (legacy_result.LCI && !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) { + return false; + } + if (legacy_result.LCR && !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) { + return false; + } + return true; +} + +bool convertLegacyVectorOfRttResultToHidl( + const std::vector& legacy_results, + std::vector* hidl_results) { + if (!hidl_results) { + return false; + } + *hidl_results = {}; + for (const auto legacy_result : legacy_results) { + V1_6::RttResult hidl_result; + if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) { + return false; + } + hidl_results->push_back(hidl_result); + } + return true; +} + +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type) { + switch (hidl_interface_type) { + case IfaceType::STA: + return legacy_hal::WIFI_INTERFACE_TYPE_STA; + case IfaceType::AP: + return legacy_hal::WIFI_INTERFACE_TYPE_AP; + case IfaceType::P2P: + return legacy_hal::WIFI_INTERFACE_TYPE_P2P; + case IfaceType::NAN: + return legacy_hal::WIFI_INTERFACE_TYPE_NAN; + } + CHECK(false); +} + +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + V1_5::IWifiChip::MultiStaUseCase use_case) { + switch (use_case) { + case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY: + return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; + case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED: + return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; + } + CHECK(false); +} + +bool convertHidlCoexUnsafeChannelToLegacy( + const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) { + if (!legacy_unsafe_channel) { + return false; + } + *legacy_unsafe_channel = {}; + switch (hidl_unsafe_channel.band) { + case V1_5::WifiBand::BAND_24GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND; + break; + case V1_5::WifiBand::BAND_5GHZ: + legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND; + break; + default: + return false; + }; + legacy_unsafe_channel->channel = hidl_unsafe_channel.channel; + legacy_unsafe_channel->power_cap_dbm = hidl_unsafe_channel.powerCapDbm; + return true; +} + +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector& hidl_unsafe_channels, + std::vector* legacy_unsafe_channels) { + if (!legacy_unsafe_channels) { + return false; + } + *legacy_unsafe_channels = {}; + for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) { + legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel; + if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(hidl_unsafe_channel, + &legacy_unsafe_channel)) { + return false; + } + legacy_unsafe_channels->push_back(legacy_unsafe_channel); + } + return true; +} + +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg) { + switch (antenna_cfg) { + case legacy_hal::WIFI_ANTENNA_1X1: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_1X1; + case legacy_hal::WIFI_ANTENNA_2X2: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_2X2; + case legacy_hal::WIFI_ANTENNA_3X3: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_3X3; + case legacy_hal::WIFI_ANTENNA_4X4: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_4X4; + default: + return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED; + } +} + +bool convertLegacyWifiRadioConfigurationToHidl( + legacy_hal::wifi_radio_configuration* radio_configuration, + V1_6::WifiRadioConfiguration* hidl_radio_configuration) { + if (!hidl_radio_configuration) { + return false; + } + *hidl_radio_configuration = {}; + hidl_radio_configuration->bandInfo = + hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band); + if (hidl_radio_configuration->bandInfo == V1_5::WifiBand::BAND_UNSPECIFIED) { + LOG(ERROR) << "Unspecified band"; + return false; + } + hidl_radio_configuration->antennaMode = + hidl_struct_util::convertLegacyAntennaConfigurationToHidl( + radio_configuration->antenna_cfg); + return true; +} + +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + WifiRadioCombinationMatrix* hidl_matrix) { + if (!hidl_matrix || !legacy_matrix) { + return false; + } + *hidl_matrix = {}; + + int num_combinations = legacy_matrix->num_radio_combinations; + std::vector radio_combinations_vec; + if (!num_combinations) { + LOG(ERROR) << "zero radio combinations"; + return false; + } + wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations; + for (int i = 0; i < num_combinations; i++) { + int num_configurations = l_radio_combinations_ptr->num_radio_configurations; + WifiRadioCombination radioCombination; + std::vector radio_configurations_vec; + if (!num_configurations) { + LOG(ERROR) << "zero radio configurations"; + return false; + } + for (int j = 0; j < num_configurations; j++) { + WifiRadioConfiguration radioConfiguration; + wifi_radio_configuration* l_radio_configurations_ptr = + &l_radio_combinations_ptr->radio_configurations[j]; + if (!hidl_struct_util::convertLegacyWifiRadioConfigurationToHidl( + l_radio_configurations_ptr, &radioConfiguration)) { + LOG(ERROR) << "Error converting wifi radio configuration"; + return false; + } + radio_configurations_vec.push_back(radioConfiguration); + } + radioCombination.radioConfigurations = radio_configurations_vec; + radio_combinations_vec.push_back(radioCombination); + l_radio_combinations_ptr = + (wifi_radio_combination*)((u8*)l_radio_combinations_ptr + + sizeof(wifi_radio_combination) + + (sizeof(wifi_radio_configuration) * num_configurations)); + } + hidl_matrix->radioCombinations = radio_combinations_vec; + return true; +} + +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h new file mode 100644 index 0000000..2d4a5f1 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_struct_util.h @@ -0,0 +1,204 @@ +/* + * 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 HIDL_STRUCT_UTIL_H_ +#define HIDL_STRUCT_UTIL_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wifi_legacy_hal.h" + +/** + * This file contains a bunch of functions to convert structs from the legacy + * HAL to HIDL and vice versa. + * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test + * suite. + */ +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_struct_util { +using namespace android::hardware::wifi::V1_0; + +// Chip conversion methods. +bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps); +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status); +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector& legacy_status_vec, + std::vector* hidl_status_vec); +bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario); +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + V1_3::IWifiChip::LatencyMode hidl_latency_mode); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario); +bool convertLegacyWifiMacInfosToHidl( + const std::vector& legacy_mac_infos, + std::vector* hidl_radio_mode_infos); +legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type); +legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( + V1_5::IWifiChip::MultiStaUseCase use_case); +bool convertHidlCoexUnsafeChannelToLegacy( + const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel, + legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel); +bool convertHidlVectorOfCoexUnsafeChannelToLegacy( + const std::vector& hidl_unsafe_channels, + std::vector* legacy_unsafe_channels); +bool convertLegacyRadioCombinationsMatrixToHidl( + legacy_hal::wifi_radio_combination_matrix* legacy_matrix, + V1_6::WifiRadioCombinationMatrix* hidl_matrix); +V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band); +V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg); + +// STA iface conversion methods. +bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set, + uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps); +bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps); +bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps); +legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band); +bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params); +// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11 +// Information Elements (IEs) +bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result, + bool has_ie_data, StaScanResult* hidl_scan_result); +// |cached_results| is assumed to not include IEs. +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector& legacy_cached_scan_results, + std::vector* hidl_scan_datas); +bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats, + V1_6::StaLinkLayerStats* hidl_stats); +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps); +bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config); +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state); +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates); +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector& legacy_fates, + std::vector* hidl_fates); + +// NAN iface conversion methods. +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len, + WifiNanStatus* wifiNanStatus); +bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanEnableRequest_1_6ToLegacy( + const V1_4::NanEnableRequest& hidl_request1, + const V1_6::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequest_1_6ToLegacy( + const V1_4::NanConfigRequest& hidl_request1, + const V1_6::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanPublishRequestToLegacy(const V1_6::NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request); +bool convertHidlNanSubscribeRequestToLegacy(const V1_0::NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request); +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request); +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const V1_0::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponseToLegacy( + const V1_0::NanRespondToDataPathIndicationRequest& hidl_response, + legacy_hal::NanDataPathIndicationResponse* legacy_response); +bool convertHidlNanDataPathInitiatorRequest_1_6ToLegacy( + const V1_6::NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponse_1_6ToLegacy( + const V1_6::NanRespondToDataPathIndicationRequest& hidl_response, + legacy_hal::NanDataPathIndicationResponse* legacy_response); + +bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus); +bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response, + V1_6::NanCapabilities* hidl_response); +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + V1_6::NanMatchInd* hidl_ind); +bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind, + NanFollowupReceivedInd* hidl_ind); +bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind); +bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind, + V1_6::NanDataPathConfirmInd* hidl_ind); +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_6::NanDataPathScheduleUpdateInd* hidl_ind); + +// RTT controller conversion methods. +bool convertHidlVectorOfRttConfigToLegacy(const std::vector& hidl_configs, + std::vector* legacy_configs); +bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info); +bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info); +bool convertHidlRttResponderToLegacy(const V1_6::RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder); +bool convertHidlWifiChannelInfoToLegacy(const V1_6::WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info); +bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder, + V1_6::RttResponder* hidl_responder); +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + V1_6::RttCapabilities* hidl_capabilities); +bool convertLegacyVectorOfRttResultToHidl( + const std::vector& legacy_results, + std::vector* hidl_results); +uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band); +uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask); +uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask); +bool convertLegacyWifiUsableChannelsToHidl( + const std::vector& legacy_usable_channels, + std::vector* hidl_usable_channels); +bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats, + V1_6::StaPeerInfo* hidl_peer_info_stats); +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + V1_6::WifiRateInfo* hidl_rate); +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // HIDL_STRUCT_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp new file mode 100644 index 0000000..358d95e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hidl_sync_util.h" + +namespace { +std::recursive_mutex g_mutex; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_sync_util { + +std::unique_lock acquireGlobalLock() { + return std::unique_lock{g_mutex}; +} + +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h new file mode 100644 index 0000000..2c1c37b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/hidl_sync_util.h @@ -0,0 +1,37 @@ +/* + * 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 HIDL_SYNC_UTIL_H_ +#define HIDL_SYNC_UTIL_H_ + +#include + +// Utility that provides a global lock to synchronize access between +// the HIDL thread and the legacy HAL's event loop. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace hidl_sync_util { +std::unique_lock acquireGlobalLock(); +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_SYNC_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp new file mode 100644 index 0000000..981bf7b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ringbuffer.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {} + +enum Ringbuffer::AppendStatus Ringbuffer::append(const std::vector& input) { + if (input.size() == 0) { + return AppendStatus::FAIL_IP_BUFFER_ZERO; + } + if (input.size() > maxSize_) { + LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped"; + return AppendStatus::FAIL_IP_BUFFER_EXCEEDED_MAXSIZE; + } + data_.push_back(input); + size_ += input.size() * sizeof(input[0]); + while (size_ > maxSize_) { + if (data_.front().size() <= 0 || data_.front().size() > maxSize_) { + LOG(ERROR) << "First buffer in the ring buffer is Invalid. Size: " + << data_.front().size(); + return AppendStatus::FAIL_RING_BUFFER_CORRUPTED; + } + size_ -= data_.front().size() * sizeof(data_.front()[0]); + data_.pop_front(); + } + return AppendStatus::SUCCESS; +} + +const std::list>& Ringbuffer::getData() const { + return data_; +} + +void Ringbuffer::clear() { + data_.clear(); + size_ = 0; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h new file mode 100644 index 0000000..c6a1e4c --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/ringbuffer.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 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 RINGBUFFER_H_ +#define RINGBUFFER_H_ + +#include +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * Ringbuffer object used to store debug data. + */ +class Ringbuffer { + public: + // Error codes for the append ring buffer operation + enum AppendStatus { + SUCCESS, + FAIL_GENERIC, + FAIL_IP_BUFFER_ZERO, + FAIL_IP_BUFFER_EXCEEDED_MAXSIZE, + FAIL_RING_BUFFER_CORRUPTED + }; + explicit Ringbuffer(size_t maxSize); + + // Appends the data buffer and deletes from the front until buffer is + // within |maxSize_|. + enum AppendStatus append(const std::vector& input); + const std::list>& getData() const; + void clear(); + + private: + std::list> data_; + size_t size_; + size_t maxSize_; +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // RINGBUFFER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/service.cpp b/wifi/wifi_legacy_service/1.0-legacy/service.cpp new file mode 100644 index 0000000..c874d8b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/service.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "wifi.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" +#include "wifi_mode_controller.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::wifi::V1_6::implementation::feature_flags::WifiFeatureFlags; +using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHal; +using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHalFactory; +using android::hardware::wifi::V1_6::implementation::mode_controller::WifiModeController; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main(int /*argc*/, char** argv) { + signal(SIGPIPE, SIG_IGN); + android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + LOG(INFO) << "Wifi Hal is booting up..."; + + configureRpcThreadpool(1, true /* callerWillJoin */); + + const auto iface_tool = std::make_shared(); + const auto legacy_hal_factory = std::make_shared(iface_tool); + + // Setup hwbinder service + android::sp service = + new android::hardware::wifi::V1_6::implementation::Wifi( + iface_tool, legacy_hal_factory, std::make_shared(), + std::make_shared()); + if (kLazyService) { + auto registrar = LazyServiceRegistrar::getInstance(); + CHECK_EQ(registrar.registerService(service), android::NO_ERROR) + << "Failed to register wifi HAL"; + } else { + CHECK_EQ(service->registerAsService(), android::NO_ERROR) << "Failed to register wifi HAL"; + } + + joinRpcThreadpool(); + + LOG(INFO) << "Wifi Hal is terminating..."; + return 0; +} diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi.cpp new file mode 100644 index 0000000..c302ce2 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "wifi.h" +#include "wifi_status_util.h" + +namespace { +// Starting Chip ID, will be assigned to primary chip +static constexpr android::hardware::wifi::V1_0::ChipId kPrimaryChipId = 0; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +Wifi::Wifi(const std::shared_ptr iface_tool, + const std::shared_ptr legacy_hal_factory, + const std::shared_ptr mode_controller, + const std::shared_ptr feature_flags) + : iface_tool_(iface_tool), + legacy_hal_factory_(legacy_hal_factory), + mode_controller_(mode_controller), + feature_flags_(feature_flags), + run_state_(RunState::STOPPED) {} + +bool Wifi::isValid() { + // This object is always valid. + return true; +} + +Return Wifi::registerEventCallback(const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal, hidl_status_cb, event_callback); +} + +Return Wifi::registerEventCallback_1_5(const sp& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal_1_5, hidl_status_cb, + event_callback); +} + +Return Wifi::isStarted() { + return run_state_ != RunState::STOPPED; +} + +Return Wifi::start(start_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal, + hidl_status_cb); +} + +Return Wifi::stop(stop_cb hidl_status_cb) { + return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, + hidl_status_cb); +} + +Return Wifi::getChipIds(getChipIds_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal, + hidl_status_cb); +} + +Return Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal, + hidl_status_cb, chip_id); +} + +Return Wifi::debug(const hidl_handle& handle, const hidl_vec&) { + LOG(INFO) << "-----------Debug is called----------------"; + if (chips_.size() == 0) { + return Void(); + } + + for (sp chip : chips_) { + if (!chip.get()) continue; + + chip->debug(handle, {}); + } + return Void(); +} + +WifiStatus Wifi::registerEventCallbackInternal( + const sp& event_callback __unused) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus Wifi::registerEventCallbackInternal_1_5( + const sp& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::startInternal() { + if (run_state_ == RunState::STARTED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); + } + WifiStatus wifi_status = initializeModeControllerAndLegacyHal(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Register the callback for subsystem restart + const auto& on_subsystem_restart_callback = [this](const std::string& error) { + WifiStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + LOG(INFO) << "Attempting to invoke onSubsystemRestart " + "callback"; + if (!callback->onSubsystemRestart(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onSubsystemRestart callback"; + } else { + LOG(INFO) << "Succeeded to invoke onSubsystemRestart " + "callback"; + } + } + }; + + // Create the chip instance once the HAL is started. + android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId; + for (auto& hal : legacy_hals_) { + chips_.push_back( + new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_, + std::make_shared(iface_tool_, hal), + feature_flags_, on_subsystem_restart_callback)); + chipId++; + } + run_state_ = RunState::STARTED; + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStart().isOk()) { + LOG(ERROR) << "Failed to invoke onStart callback"; + }; + } + LOG(INFO) << "Wifi HAL started"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL start failed"; + // Clear the event callback objects since the HAL start failed. + event_cb_handler_.invalidate(); + } + return wifi_status; +} + +WifiStatus Wifi::stopInternal( + /* NONNULL */ std::unique_lock* lock) { + if (run_state_ == RunState::STOPPED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping"); + } + // Clear the chip object and its child objects since the HAL is now + // stopped. + for (auto& chip : chips_) { + if (chip.get()) { + chip->invalidate(); + chip.clear(); + } + } + chips_.clear(); + WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStop().isOk()) { + LOG(ERROR) << "Failed to invoke onStop callback"; + }; + } + LOG(INFO) << "Wifi HAL stopped"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL stop failed"; + } + // Clear the event callback objects since the HAL is now stopped. + event_cb_handler_.invalidate(); + return wifi_status; +} + +std::pair> Wifi::getChipIdsInternal() { + std::vector chip_ids; + + for (auto& chip : chips_) { + ChipId chip_id = getChipIdFromWifiChip(chip); + if (chip_id != UINT32_MAX) chip_ids.emplace_back(chip_id); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)}; +} + +std::pair> Wifi::getChipInternal(ChipId chip_id) { + for (auto& chip : chips_) { + ChipId cand_id = getChipIdFromWifiChip(chip); + if ((cand_id != UINT32_MAX) && (cand_id == chip_id)) + return {createWifiStatus(WifiStatusCode::SUCCESS), chip}; + } + + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; +} + +WifiStatus Wifi::initializeModeControllerAndLegacyHal() { + if (!mode_controller_->initialize()) { + LOG(ERROR) << "Failed to initialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + + legacy_hals_ = legacy_hal_factory_->getHals(); + if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + int index = 0; // for failure log + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error legacy_status = hal->initialize(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // Currently WifiLegacyHal::initialize does not allocate extra mem, + // only initializes the function table. If this changes, need to + // implement WifiLegacyHal::deinitialize and deinitalize the + // HALs already initialized + LOG(ERROR) << "Failed to initialize legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + index++; + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( + /* NONNULL */ std::unique_lock* lock) { + legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS; + int index = 0; + + run_state_ = RunState::STOPPING; + for (auto& hal : legacy_hals_) { + legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {}); + if (tmp != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL index: " << index + << " error: " << legacyErrorToString(legacy_status); + legacy_status = tmp; + } + index++; + } + run_state_ = RunState::STOPPED; + + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "One or more legacy HALs failed to stop"; + return createWifiStatusFromLegacyError(legacy_status); + } + if (!mode_controller_->deinitialize()) { + LOG(ERROR) << "Failed to deinitialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +ChipId Wifi::getChipIdFromWifiChip(sp& chip) { + ChipId chip_id = UINT32_MAX; + if (chip.get()) { + chip->getId([&](WifiStatus status, uint32_t id) { + if (status.code == WifiStatusCode::SUCCESS) { + chip_id = id; + } + }); + } + + return chip_id; +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi.h b/wifi/wifi_legacy_service/1.0-legacy/wifi.h new file mode 100644 index 0000000..435358e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi.h @@ -0,0 +1,105 @@ +/* + * 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 WIFI_H_ +#define WIFI_H_ + +// HACK: NAN is a macro defined in math.h, which can be included in various +// headers. This wifi HAL uses an enum called NAN, which does not compile when +// the macro is defined. Undefine NAN to work around it. +#undef NAN +#include + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_chip.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_factory.h" +#include "wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * Root HIDL interface object used to control the Wifi HAL. + */ +class Wifi : public V1_6::IWifi { + public: + Wifi(const std::shared_ptr iface_tool, + const std::shared_ptr legacy_hal_factory, + const std::shared_ptr mode_controller, + const std::shared_ptr feature_flags); + + bool isValid(); + + // HIDL methods exposed. + Return registerEventCallback(const sp& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return registerEventCallback_1_5(const sp& event_callback, + registerEventCallback_1_5_cb hidl_status_cb) override; + Return isStarted() override; + Return start(start_cb hidl_status_cb) override; + Return stop(stop_cb hidl_status_cb) override; + Return getChipIds(getChipIds_cb hidl_status_cb) override; + Return getChip(ChipId chip_id, getChip_cb hidl_status_cb) override; + Return debug(const hidl_handle& handle, const hidl_vec& options) override; + + private: + enum class RunState { STOPPED, STARTED, STOPPING }; + + // Corresponding worker functions for the HIDL methods. + WifiStatus registerEventCallbackInternal( + const sp& event_callback __unused); + WifiStatus registerEventCallbackInternal_1_5( + const sp& event_callback); + WifiStatus startInternal(); + WifiStatus stopInternal(std::unique_lock* lock); + std::pair> getChipIdsInternal(); + std::pair> getChipInternal(ChipId chip_id); + + WifiStatus initializeModeControllerAndLegacyHal(); + WifiStatus stopLegacyHalAndDeinitializeModeController( + std::unique_lock* lock); + ChipId getChipIdFromWifiChip(sp& chip); + + // Instance is created in this root level |IWifi| HIDL interface object + // and shared with all the child HIDL interface objects. + std::shared_ptr iface_tool_; + std::shared_ptr legacy_hal_factory_; + std::shared_ptr mode_controller_; + std::vector> legacy_hals_; + std::shared_ptr feature_flags_; + RunState run_state_; + std::vector> chips_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(Wifi); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp new file mode 100644 index 0000000..b2957db --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_ap_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiApIface::WifiApIface(const std::string& ifname, const std::vector& instances, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), + instances_(instances), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) {} + +void WifiApIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiApIface::isValid() { + return is_valid_; +} + +std::string WifiApIface::getName() { + return ifname_; +} + +void WifiApIface::removeInstance(std::string instance) { + instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end()); +} + +Return WifiApIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getNameInternal, hidl_status_cb); +} + +Return WifiApIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getTypeInternal, hidl_status_cb); +} + +Return WifiApIface::setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setCountryCodeInternal, hidl_status_cb, code); +} + +Return WifiApIface::getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getValidFrequenciesForBandInternal, hidl_status_cb, band); +} + +Return WifiApIface::setMacAddress(const hidl_array& mac, + setMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setMacAddressInternal, hidl_status_cb, mac); +} + +Return WifiApIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getFactoryMacAddressInternal, hidl_status_cb, + instances_.size() > 0 ? instances_[0] : ifname_); +} + +Return WifiApIface::resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::resetToFactoryMacAddressInternal, hidl_status_cb); +} + +Return WifiApIface::getBridgedInstances(getBridgedInstances_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getBridgedInstancesInternal, hidl_status_cb); +} + +std::pair WifiApIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiApIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP}; +} + +WifiStatus WifiApIface::setCountryCodeInternal(const std::array& code) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode( + instances_.size() > 0 ? instances_[0] : ifname_, code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> +WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector valid_frequencies; + std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand( + instances_.size() > 0 ? instances_[0] : ifname_, + hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} + +WifiStatus WifiApIface::setMacAddressInternal(const std::array& mac) { + // Support random MAC up to 2 interfaces + if (instances_.size() == 2) { + int rbyte = 1; + for (auto const& intf : instances_) { + std::array rmac = mac; + // reverse the bits to avoid collision + rmac[rbyte] = 0xff - rmac[rbyte]; + if (!iface_util_.lock()->setMacAddress(intf, rmac)) { + LOG(INFO) << "Failed to set random mac address on " << intf; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + rbyte++; + } + } + // It also needs to set mac address for bridged interface, otherwise the mac + // address of bridged interface will be changed after one of instance + // down. + if (!iface_util_.lock()->setMacAddress(ifname_, mac)) { + LOG(ERROR) << "Fail to config MAC for interface " << ifname_; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiApIface::getFactoryMacAddressInternal( + const std::string& ifaceName) { + std::array mac = iface_util_.lock()->getFactoryMacAddress(ifaceName); + if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; +} + +WifiStatus WifiApIface::resetToFactoryMacAddressInternal() { + std::pair> getMacResult; + if (instances_.size() == 2) { + for (auto const& intf : instances_) { + getMacResult = getFactoryMacAddressInternal(intf); + LOG(DEBUG) << "Reset MAC to factory MAC on " << intf; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(intf, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + // It needs to set mac address for bridged interface, otherwise the mac + // address of the bridged interface will be changed after one of the + // instance down. Thus we are generating a random MAC address for the + // bridged interface even if we got the request to reset the Factory + // MAC. Since the bridged interface is an internal interface for the + // operation of bpf and others networking operation. + if (!iface_util_.lock()->setMacAddress(ifname_, + iface_util_.lock()->createRandomMacAddress())) { + LOG(ERROR) << "Fail to config MAC for bridged interface " << ifname_; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } else { + getMacResult = getFactoryMacAddressInternal(ifname_); + LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_; + if (getMacResult.first.code != WifiStatusCode::SUCCESS || + !iface_util_.lock()->setMacAddress(ifname_, getMacResult.second)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiApIface::getBridgedInstancesInternal() { + std::vector instances; + for (const auto& instance_name : instances_) { + instances.push_back(instance_name); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), instances}; +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h new file mode 100644 index 0000000..d1c0642 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_ap_iface.h @@ -0,0 +1,89 @@ +/* + * 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 WIFI_AP_IFACE_H_ +#define WIFI_AP_IFACE_H_ + +#include +#include + +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a AP Iface instance. + */ +class WifiApIface : public V1_5::IWifiApIface { + public: + WifiApIface(const std::string& ifname, const std::vector& instances, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + void removeInstance(std::string instance); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) override; + Return getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) override; + Return setMacAddress(const hidl_array& mac, + setMacAddress_cb hidl_status_cb) override; + Return getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override; + Return resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) override; + + Return getBridgedInstances(getBridgedInstances_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus setCountryCodeInternal(const std::array& code); + std::pair> getValidFrequenciesForBandInternal( + V1_0::WifiBand band); + WifiStatus setMacAddressInternal(const std::array& mac); + std::pair> getFactoryMacAddressInternal( + const std::string& ifaceName); + WifiStatus resetToFactoryMacAddressInternal(); + std::pair> getBridgedInstancesInternal(); + + std::string ifname_; + std::vector instances_; + std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiApIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_AP_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp new file mode 100644 index 0000000..08ef368 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.cpp @@ -0,0 +1,2109 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_chip.h" +#include "wifi_status_util.h" + +#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-" + +namespace { +using android::sp; +using android::base::unique_fd; +using android::hardware::hidl_string; +using android::hardware::hidl_vec; +using android::hardware::wifi::V1_0::ChipModeId; +using android::hardware::wifi::V1_0::IfaceType; +using android::hardware::wifi::V1_0::IWifiChip; + +constexpr char kCpioMagic[] = "070701"; +constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3; +constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10; +constexpr uint32_t kMaxRingBufferFileNum = 20; +constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/"; +constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface"; +constexpr char kNoActiveWlanIfaceNamePropertyValue[] = ""; +constexpr unsigned kMaxWlanIfaces = 5; +constexpr char kApBridgeIfacePrefix[] = "ap_br_"; + +template +void invalidateAndClear(std::vector>& ifaces, sp iface) { + iface->invalidate(); + ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end()); +} + +template +void invalidateAndClearAll(std::vector>& ifaces) { + for (const auto& iface : ifaces) { + iface->invalidate(); + } + ifaces.clear(); +} + +template +std::vector getNames(std::vector>& ifaces) { + std::vector names; + for (const auto& iface : ifaces) { + names.emplace_back(iface->getName()); + } + return names; +} + +template +sp findUsingName(std::vector>& ifaces, const std::string& name) { + std::vector names; + for (const auto& iface : ifaces) { + if (name == iface->getName()) { + return iface; + } + } + return nullptr; +} + +std::string getWlanIfaceName(unsigned idx) { + if (idx >= kMaxWlanIfaces) { + CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces; + return {}; + } + + std::array buffer; + if (idx == 0 || idx == 1) { + const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface"; + auto res = property_get(altPropName, buffer.data(), nullptr); + if (res > 0) return buffer.data(); + } + std::string propName = "wifi.interface." + std::to_string(idx); + auto res = property_get(propName.c_str(), buffer.data(), nullptr); + if (res > 0) return buffer.data(); + + return "wlan" + std::to_string(idx); +} + +// Returns the dedicated iface name if defined. +// Returns two ifaces in bridged mode. +std::vector getPredefinedApIfaceNames(bool is_bridged) { + std::vector ifnames; + std::array buffer; + buffer.fill(0); + if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) { + return ifnames; + } + ifnames.push_back(buffer.data()); + if (is_bridged) { + buffer.fill(0); + if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) { + return ifnames; + } + ifnames.push_back(buffer.data()); + } + return ifnames; +} + +std::string getPredefinedP2pIfaceName() { + std::array primaryIfaceName; + char p2pParentIfname[100]; + std::string p2pDevIfName = ""; + std::array buffer; + property_get("wifi.direct.interface", buffer.data(), "p2p0"); + if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) { + /* Get the p2p parent interface name from p2p device interface name set + * in property */ + strlcpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX), + strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)); + if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(), nullptr) == 0) { + return buffer.data(); + } + /* Check if the parent interface derived from p2p device interface name + * is active */ + if (strncmp(p2pParentIfname, primaryIfaceName.data(), + strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) != 0) { + /* + * Update the predefined p2p device interface parent interface name + * with current active wlan interface + */ + p2pDevIfName += P2P_MGMT_DEVICE_PREFIX; + p2pDevIfName += primaryIfaceName.data(); + LOG(INFO) << "update the p2p device interface name to " << p2pDevIfName.c_str(); + return p2pDevIfName; + } + } + return buffer.data(); +} + +// Returns the dedicated iface name if one is defined. +std::string getPredefinedNanIfaceName() { + std::array buffer; + if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) { + return {}; + } + return buffer.data(); +} + +void setActiveWlanIfaceNameProperty(const std::string& ifname) { + auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data()); + if (res != 0) { + PLOG(ERROR) << "Failed to set active wlan iface name property"; + } +} + +// delete files that meet either conditions: +// 1. older than a predefined time in the wifi tombstone dir. +// 2. Files in excess to a predefined amount, starting from the oldest ones +bool removeOldFilesInternal() { + time_t now = time(0); + const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds; + std::unique_ptr dir_dump(opendir(kTombstoneFolderPath), closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return false; + } + struct dirent* dp; + bool success = true; + std::list> valid_files; + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + struct stat cur_file_stat; + std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + success = false; + continue; + } + const time_t cur_file_time = cur_file_stat.st_mtime; + valid_files.push_back(std::pair(cur_file_time, cur_file_path)); + } + valid_files.sort(); // sort the list of files by last modified time from + // small to big. + uint32_t cur_file_count = valid_files.size(); + for (auto cur_file : valid_files) { + if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) { + if (unlink(cur_file.second.c_str()) != 0) { + PLOG(ERROR) << "Error deleting file"; + success = false; + } + cur_file_count--; + } else { + break; + } + } + return success; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) { + const int buf_size = 32 * 1024; + std::array read_buf; + ssize_t llen = snprintf( + read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X", + kCpioMagic, static_cast(st.st_ino), st.st_mode, st.st_uid, st.st_gid, + static_cast(st.st_nlink), static_cast(st.st_mtime), + static_cast(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev), + minor(st.st_rdev), static_cast(file_name_len), 0); + if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) { + PLOG(ERROR) << "Error writing cpio header to file " << file_name; + return false; + } + if (write(out_fd, file_name, file_name_len) == -1) { + PLOG(ERROR) << "Error writing filename to file " << file_name; + return false; + } + + // NUL Pad header up to 4 multiple bytes. + llen = (llen + file_name_len) % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file " << file_name; + return false; + } + } + return true; +} + +// Helper function for |cpioArchiveFilesInDir| +size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) { + // writing content of file + std::array read_buf; + ssize_t llen = st.st_size; + size_t n_error = 0; + while (llen > 0) { + ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size()); + if (bytes_read == -1) { + PLOG(ERROR) << "Error reading file"; + return ++n_error; + } + llen -= bytes_read; + if (write(out_fd, read_buf.data(), bytes_read) == -1) { + PLOG(ERROR) << "Error writing data to file"; + return ++n_error; + } + if (bytes_read == 0) { // this should never happen, but just in case + // to unstuck from while loop + PLOG(ERROR) << "Unexpected read result"; + n_error++; + break; + } + } + llen = st.st_size % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file"; + return ++n_error; + } + } + return n_error; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteFileTrailer(int out_fd) { + const int buf_size = 4096; + std::array read_buf; + read_buf.fill(0); + ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0); + if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) { + PLOG(ERROR) << "Error writing trailing bytes"; + return false; + } + return true; +} + +// Archives all files in |input_dir| and writes result into |out_fd| +// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive" +// portion +size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { + struct dirent* dp; + size_t n_error = 0; + std::unique_ptr dir_dump(opendir(input_dir), closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return ++n_error; + } + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + struct stat st; + const std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &st) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + n_error++; + continue; + } + const int fd_read = open(cur_file_path.c_str(), O_RDONLY); + if (fd_read == -1) { + PLOG(ERROR) << "Failed to open file " << cur_file_path; + n_error++; + continue; + } + std::string file_name_with_last_modified_time = + cur_file_name + "-" + std::to_string(st.st_mtime); + // string.size() does not include the null terminator. The cpio FreeBSD + // file header expects the null character to be included in the length. + const size_t file_name_len = file_name_with_last_modified_time.size() + 1; + unique_fd file_auto_closer(fd_read); + if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(), + file_name_len)) { + return ++n_error; + } + size_t write_error = cpioWriteFileContent(fd_read, out_fd, st); + if (write_error) { + return n_error + write_error; + } + } + if (!cpioWriteFileTrailer(out_fd)) { + return ++n_error; + } + return n_error; +} + +// Helper function to create a non-const char*. +std::vector makeCharVec(const std::string& str) { + std::vector vec(str.size() + 1); + vec.assign(str.begin(), str.end()); + vec.push_back('\0'); + return vec; +} + +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +WifiChip::WifiChip(ChipId chip_id, bool is_primary, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller, + const std::shared_ptr iface_util, + const std::weak_ptr feature_flags, + const std::function& handler) + : chip_id_(chip_id), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + iface_util_(iface_util), + is_valid_(true), + current_mode_id_(feature_flags::chip_mode_ids::kInvalid), + modes_(feature_flags.lock()->getChipModes(is_primary)), + debug_ring_buffer_cb_registered_(false), + subsystemCallbackHandler_(handler) { + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); +} + +void WifiChip::invalidate() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + invalidateAndRemoveAllIfaces(); + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiChip::isValid() { + return is_valid_; +} + +std::set> WifiChip::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return WifiChip::getId(getId_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal, + hidl_status_cb); +} + +// Deprecated support for this callback +Return WifiChip::registerEventCallback(const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal, hidl_status_cb, + event_callback); +} + +Return WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal, hidl_status_cb); +} + +Return WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal, hidl_status_cb); +} + +Return WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) { + return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::configureChipInternal, hidl_status_cb, mode_id); +} + +Return WifiChip::getMode(getMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getModeInternal, hidl_status_cb); +} + +Return WifiChip::requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestChipDebugInfoInternal, hidl_status_cb); +} + +Return WifiChip::requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestDriverDebugDumpInternal, hidl_status_cb); +} + +Return WifiChip::requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestFirmwareDebugDumpInternal, hidl_status_cb); +} + +Return WifiChip::createApIface(createApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createApIfaceInternal, hidl_status_cb); +} + +Return WifiChip::createBridgedApIface(createBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createBridgedApIfaceInternal, hidl_status_cb); +} + +Return WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceNamesInternal, hidl_status_cb); +} + +Return WifiChip::getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeApIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::removeIfaceInstanceFromBridgedApIface( + const hidl_string& ifname, const hidl_string& ifInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, hidl_status_cb, + ifname, ifInstanceName); +} + +Return WifiChip::createNanIface(createNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createNanIfaceInternal, hidl_status_cb); +} + +Return WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceNamesInternal, hidl_status_cb); +} + +Return WifiChip::getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::removeNanIface(const hidl_string& ifname, removeNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeNanIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createP2pIfaceInternal, hidl_status_cb); +} + +Return WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb); +} + +Return WifiChip::getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::removeP2pIface(const hidl_string& ifname, removeP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeP2pIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::createStaIface(createStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createStaIfaceInternal, hidl_status_cb); +} + +Return WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceNamesInternal, hidl_status_cb); +} + +Return WifiChip::getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::removeStaIface(const hidl_string& ifname, removeStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeStaIfaceInternal, hidl_status_cb, ifname); +} + +Return WifiChip::createRttController(const sp& bound_iface, + createRttController_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal, hidl_status_cb, bound_iface); +} + +Return WifiChip::getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugRingBuffersStatusInternal, hidl_status_cb); +} + +Return WifiChip::startLoggingToDebugRingBuffer( + const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::startLoggingToDebugRingBufferInternal, hidl_status_cb, + ring_name, verbose_level, max_interval_in_sec, min_data_size_in_bytes); +} + +Return WifiChip::forceDumpToDebugRingBuffer(const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::forceDumpToDebugRingBufferInternal, hidl_status_cb, + ring_name); +} + +Return WifiChip::flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::flushRingBufferToFileInternal, hidl_status_cb); +} + +Return WifiChip::stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::stopLoggingToDebugRingBufferInternal, hidl_status_cb); +} + +Return WifiChip::getDebugHostWakeReasonStats(getDebugHostWakeReasonStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugHostWakeReasonStatsInternal, hidl_status_cb); +} + +Return WifiChip::enableDebugErrorAlerts(bool enable, + enableDebugErrorAlerts_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::enableDebugErrorAlertsInternal, hidl_status_cb, enable); +} + +Return WifiChip::selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal, hidl_status_cb, scenario); +} + +Return WifiChip::resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::resetTxPowerScenarioInternal, hidl_status_cb); +} + +Return WifiChip::setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setLatencyModeInternal, hidl_status_cb, mode); +} + +Return WifiChip::registerEventCallback_1_2( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal_1_2, hidl_status_cb, + event_callback); +} + +Return WifiChip::selectTxPowerScenario_1_2(TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario); +} + +Return WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_3, hidl_status_cb); +} + +Return WifiChip::getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_5, hidl_status_cb); +} + +Return WifiChip::debug(const hidl_handle& handle, const hidl_vec&) { + if (handle != nullptr && handle->numFds >= 1) { + { + std::unique_lock lk(lock_t); + for (const auto& item : ringbuffer_map_) { + forceDumpToDebugRingBufferInternal(item.first); + } + // unique_lock unlocked here + } + usleep(100 * 1000); // sleep for 100 milliseconds to wait for + // ringbuffer updates. + int fd = handle->data[0]; + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath); + if (n_error != 0) { + LOG(ERROR) << n_error << " errors occured in cpio function"; + } + fsync(fd); + } else { + LOG(ERROR) << "File handle error"; + } + return Void(); +} + +Return WifiChip::createRttController_1_4(const sp& bound_iface, + createRttController_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal_1_4, hidl_status_cb, bound_iface); +} + +Return WifiChip::registerEventCallback_1_4( + const sp& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal_1_4, hidl_status_cb, + event_callback); +} + +Return WifiChip::setMultiStaPrimaryConnection( + const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaPrimaryConnectionInternal, hidl_status_cb, ifname); +} + +Return WifiChip::setMultiStaUseCase(MultiStaUseCase use_case, + setMultiStaUseCase_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setMultiStaUseCaseInternal, hidl_status_cb, use_case); +} + +Return WifiChip::setCoexUnsafeChannels(const hidl_vec& unsafeChannels, + hidl_bitfield restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setCoexUnsafeChannelsInternal, hidl_status_cb, unsafeChannels, + restrictions); +} + +Return WifiChip::setCountryCode(const hidl_array& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiChip::setCountryCodeInternal, hidl_status_cb, code); +} + +Return WifiChip::getUsableChannels( + WifiBand band, hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_cb _hidl_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getUsableChannelsInternal, _hidl_cb, band, ifaceModeMask, + filterMask); +} + +Return WifiChip::triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::triggerSubsystemRestartInternal, hidl_status_cb); +} + +Return WifiChip::createRttController_1_6(const sp& bound_iface, + createRttController_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal_1_6, hidl_status_cb, bound_iface); +} + +Return WifiChip::getUsableChannels_1_6( + WifiBand band, hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_1_6_cb _hidl_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getUsableChannelsInternal_1_6, _hidl_cb, band, ifaceModeMask, + filterMask); +} + +Return WifiChip::getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getSupportedRadioCombinationsMatrixInternal, hidl_status_cb); +} + +Return WifiChip::getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal_1_6, hidl_status_cb); +} + +void WifiChip::QcRemoveAndClearDynamicIfaces() { + for (const auto& iface : created_ap_ifaces_) { + std::string ifname = iface->getName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + } + + for (const auto& iface : created_sta_ifaces_) { + std::string ifname = iface->getName(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + } + + // created_ap/sta_ifaces are also part of sta/ap_ifaces. + // Do no invalidate here. + + created_ap_ifaces_.clear(); + created_sta_ifaces_.clear(); +} + +void WifiChip::invalidateAndRemoveAllIfaces() { + QcRemoveAndClearDynamicIfaces(); + invalidateAndClearBridgedApAll(); + invalidateAndClearAll(ap_ifaces_); + invalidateAndClearAll(nan_ifaces_); + invalidateAndClearAll(p2p_ifaces_); + invalidateAndClearAll(sta_ifaces_); + // Since all the ifaces are invalid now, all RTT controller objects + // using those ifaces also need to be invalidated. + for (const auto& rtt : rtt_controllers_) { + rtt->invalidate(); + } + rtt_controllers_.clear(); +} + +void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) { + for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) { + auto nan_iface = *it; + if (nan_iface->getName() == removed_iface_name) { + nan_iface->invalidate(); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::NAN, removed_iface_name).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + it = nan_ifaces_.erase(it); + } else { + ++it; + } + } + + for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) { + auto rtt = *it; + if (rtt->getIfaceName() == removed_iface_name) { + rtt->invalidate(); + it = rtt_controllers_.erase(it); + } else { + ++it; + } + } +} + +std::pair WifiChip::getIdInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_}; +} + +WifiStatus WifiChip::registerEventCallbackInternal( + const sp& /* event_callback */) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +std::pair WifiChip::getCapabilitiesInternal() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair> +WifiChip::getAvailableModesInternal() { + // Deprecated support -- use getAvailableModes_1_6 for more granular concurrency combinations. + std::vector modes_1_0 = {}; + for (const auto& mode_1_6 : modes_) { + std::vector combos_1_0; + for (const auto& combo_1_6 : mode_1_6.availableCombinations) { + std::vector limits_1_0; + for (const auto& limit_1_6 : combo_1_6.limits) { + std::vector types_1_0; + for (IfaceConcurrencyType type_1_6 : limit_1_6.types) { + switch (type_1_6) { + case IfaceConcurrencyType::STA: + types_1_0.push_back(IfaceType::STA); + break; + case IfaceConcurrencyType::AP: + types_1_0.push_back(IfaceType::AP); + break; + case IfaceConcurrencyType::AP_BRIDGED: + // Ignore AP_BRIDGED + break; + case IfaceConcurrencyType::P2P: + types_1_0.push_back(IfaceType::P2P); + break; + case IfaceConcurrencyType::NAN: + types_1_0.push_back(IfaceType::NAN); + break; + } + } + if (types_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipIfaceCombinationLimit limit_1_0; + limit_1_0.types = hidl_vec(types_1_0); + limit_1_0.maxIfaces = limit_1_6.maxIfaces; + limits_1_0.push_back(limit_1_0); + } + if (limits_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipIfaceCombination combo_1_0; + combo_1_0.limits = hidl_vec(limits_1_0); + combos_1_0.push_back(combo_1_0); + } + if (combos_1_0.empty()) { + continue; + } + V1_0::IWifiChip::ChipMode mode_1_0; + mode_1_0.id = mode_1_6.id; + mode_1_0.availableCombinations = hidl_vec(combos_1_0); + modes_1_0.push_back(mode_1_0); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), modes_1_0}; +} + +WifiStatus WifiChip::configureChipInternal( + /* NONNULL */ std::unique_lock* lock, ChipModeId mode_id) { + if (!isValidModeId(mode_id)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + if (mode_id == current_mode_id_) { + LOG(DEBUG) << "Already in the specified mode " << mode_id; + return createWifiStatus(WifiStatusCode::SUCCESS); + } + WifiStatus status = handleChipConfiguration(lock, mode_id); + if (status.code != WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigureFailure(status).isOk()) { + LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback"; + } + } + return status; + } + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigured(mode_id).isOk()) { + LOG(ERROR) << "Failed to invoke onChipReconfigured callback"; + } + } + current_mode_id_ = mode_id; + LOG(INFO) << "Configured chip in mode " << mode_id; + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_); + + return status; +} + +std::pair WifiChip::getModeInternal() { + if (!isValidModeId(current_mode_id_)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), current_mode_id_}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; +} + +std::pair WifiChip::requestChipDebugInfoInternal() { + V1_4::IWifiChip::ChipDebugInfo result; + legacy_hal::wifi_error legacy_status; + std::string driver_desc; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status); + WifiStatus status = + createWifiStatusFromLegacyError(legacy_status, "failed to get driver version"); + return {status, result}; + } + result.driverDescription = driver_desc.c_str(); + + std::string firmware_desc; + std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status); + WifiStatus status = + createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version"); + return {status, result}; + } + result.firmwareDescription = firmware_desc.c_str(); + + return {createWifiStatus(WifiStatusCode::SUCCESS), result}; +} + +std::pair> WifiChip::requestDriverDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector driver_dump; + std::tie(legacy_status, driver_dump) = + legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), std::vector()}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump}; +} + +std::pair> WifiChip::requestFirmwareDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector firmware_dump; + std::tie(legacy_status, firmware_dump) = + legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump}; +} + +WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) { + legacy_hal::wifi_error legacy_status; + legacy_status = legacy_hal_.lock()->createVirtualInterface( + apVirtIf, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << apVirtIf << " " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +sp WifiChip::newWifiApIface(std::string& ifname) { + std::vector ap_instances; + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + ap_instances = it.second; + } + } + sp iface = new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_); + ap_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return iface; +} + +std::pair> WifiChip::createApIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool iface_created = false; + std::string ifname = allocateApIfaceName(); + if (!if_nametoindex(ifname.c_str())) { + WifiStatus status = createVirtualApInterface(ifname); + if (status.code != WifiStatusCode::SUCCESS) { + return {status, {}}; + } + iface_created = true; + } + sp iface = newWifiApIface(ifname); + if (iface_created) created_ap_ifaces_.push_back(iface); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> WifiChip::createBridgedApIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::vector ap_instances = allocateBridgedApInstanceNames(); + if (ap_instances.size() < 2) { + LOG(ERROR) << "Fail to allocate two instances"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0]; + for (int i = 0; i < 2; i++) { + WifiStatus status = createVirtualApInterface(ap_instances[i]); + if (status.code != WifiStatusCode::SUCCESS) { + if (i != 0) { // The failure happened when creating second virtual + // iface. + legacy_hal_.lock()->deleteVirtualInterface( + ap_instances.front()); // Remove the first virtual iface. + } + return {status, {}}; + } + } + br_ifaces_ap_instances_[br_ifname] = ap_instances; + if (!iface_util_->createBridge(br_ifname)) { + LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str(); + deleteApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + for (auto const& instance : ap_instances) { + // Bind ap instance interface to AP bridge + if (!iface_util_->addIfaceToBridge(br_ifname, instance)) { + LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str(); + deleteApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + } + sp iface = newWifiApIface(br_ifname); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> WifiChip::getApIfaceNamesInternal() { + if (ap_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)}; +} + +std::pair> WifiChip::getApIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + // Note: This is probably not required because we never create + // nan/rtt objects over AP iface. But, there is no harm to do it + // here and not make that assumption all over the place. + invalidateAndRemoveDependencies(ifname); + if (findUsingName(created_ap_ifaces_, ifname) != nullptr) { + invalidateAndClear(created_ap_ifaces_, iface); + } + invalidateAndClear(ap_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal( + const std::string& ifname, const std::string& ifInstanceName) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get() || ifInstanceName.empty()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Requires to remove one of the instance in bridge mode + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ifname) { + std::vector ap_instances = it.second; + for (auto const& iface : ap_instances) { + if (iface == ifInstanceName) { + if (!iface_util_->removeIfaceFromBridge(it.first, iface)) { + LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from " + << ifname; + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(iface); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to del interface: " << iface << " " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + ap_instances.erase( + std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName), + ap_instances.end()); + br_ifaces_ap_instances_[ifname] = ap_instances; + break; + } + } + break; + } + } + iface->removeInstance(ifInstanceName); + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createNanIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool is_dedicated_iface = true; + std::string ifname = getPredefinedNanIfaceName(); + if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) { + // Use the first shared STA iface (wlan0) if a dedicated aware iface is + // not defined. + ifname = getFirstActiveWlanIfaceName(); + is_dedicated_iface = false; + } + sp iface = new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_); + nan_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> WifiChip::getNanIfaceNamesInternal() { + if (nan_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)}; +} + +std::pair> WifiChip::getNanIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(nan_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createP2pIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = getPredefinedP2pIfaceName(); + sp iface = new WifiP2pIface(ifname, legacy_hal_); + p2p_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> WifiChip::getP2pIfaceNamesInternal() { + if (p2p_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)}; +} + +std::pair> WifiChip::getP2pIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(p2p_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createStaIfaceInternal() { + if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + bool iface_created = false; + std::string ifname = allocateStaIfaceName(); + if (!if_nametoindex(ifname.c_str())) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->createVirtualInterface( + ifname, + hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA)); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to add interface: " << ifname << " " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + iface_created = true; + } + sp iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); + sta_ifaces_.push_back(iface); + if (iface_created) created_sta_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> WifiChip::getStaIfaceNamesInternal() { + if (sta_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)}; +} + +std::pair> WifiChip::getStaIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + invalidateAndRemoveDependencies(ifname); + if (findUsingName(created_sta_ifaces_, ifname) != nullptr) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deleteVirtualInterface(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << ifname << " " + << legacyErrorToString(legacy_status); + } + invalidateAndClear(created_sta_ifaces_, iface); + } + invalidateAndClear(sta_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiChip::createRttControllerInternal( + const sp& /*bound_iface*/) { + LOG(ERROR) << "createRttController is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair> +WifiChip::getDebugRingBuffersStatusInternal() { + legacy_hal::wifi_error legacy_status; + std::vector legacy_ring_buffer_status_vec; + std::tie(legacy_status, legacy_ring_buffer_status_vec) = + legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_ring_buffer_status_vec; + if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl( + legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_ring_buffer_status_vec}; +} + +WifiStatus WifiChip::startLoggingToDebugRingBufferInternal( + const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging( + getFirstActiveWlanIfaceName(), ring_name, + static_cast::type>(verbose_level), + max_interval_in_sec, min_data_size_in_bytes); + ringbuffer_map_.insert( + std::pair(ring_name, Ringbuffer(kMaxBufferSizeBytes))); + // if verbose logging enabled, turn up HAL daemon logging as well. + if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) { + android::base::SetMinimumLogSeverity(android::base::DEBUG); + } else { + android::base::SetMinimumLogSeverity(android::base::VERBOSE); + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(const hidl_string& ring_name) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name); + + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::flushRingBufferToFileInternal() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName()); + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = false; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair +WifiChip::getDebugHostWakeReasonStatsInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::WakeReasonStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + WifiDebugHostWakeReasonStats hidl_stats; + if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats, &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { + legacy_hal::wifi_error legacy_status; + if (enable) { + android::wp weak_ptr_this(this); + const auto& on_alert_callback = [weak_ptr_this](int32_t error_code, + std::vector debug_data) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) { + LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback"; + } + } + }; + legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler( + getFirstActiveWlanIfaceName(), on_alert_callback); + } else { + legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler( + getFirstActiveWlanIfaceName()); + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::resetTxPowerScenarioInternal() { + auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName()); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) { + auto legacy_status = legacy_hal_.lock()->setLatencyMode( + getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlLatencyModeToLegacy(mode)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerEventCallbackInternal_1_2( + const sp& /* event_callback */) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiChip::getCapabilitiesInternal_1_3() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair WifiChip::getCapabilitiesInternal_1_5() { + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + uint32_t legacy_logger_feature_set; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // some devices don't support querying logger feature set + legacy_logger_feature_set = 0; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair> WifiChip::createRttControllerInternal_1_4( + const sp& /*bound_iface*/) { + LOG(ERROR) << "createRttController_1_4 is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiChip::registerEventCallbackInternal_1_4( + const sp& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) { + auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) { + auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase( + hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCoexUnsafeChannelsInternal(std::vector unsafe_channels, + uint32_t restrictions) { + std::vector legacy_unsafe_channels; + if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels, + &legacy_unsafe_channels)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + uint32_t legacy_restrictions = 0; + if (restrictions & CoexRestriction::WIFI_DIRECT) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT; + } + if (restrictions & CoexRestriction::SOFTAP) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP; + } + if (restrictions & CoexRestriction::WIFI_AWARE) { + legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE; + } + auto legacy_status = + legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setCountryCodeInternal(const std::array& code) { + auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> WifiChip::getUsableChannelsInternal( + WifiBand /*band*/, uint32_t /*ifaceModeMask*/, uint32_t /*filterMask*/) { + LOG(ERROR) << "getUsableChannels is not supported on this HAL"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiChip::triggerSubsystemRestartInternal() { + auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart(); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> WifiChip::createRttControllerInternal_1_6( + const sp& bound_iface) { + if (sta_ifaces_.size() == 0 && + !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) { + LOG(ERROR) << "createRttControllerInternal_1_6: Chip cannot support STAs " + "(and RTT by extension)"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + sp rtt = + new WifiRttController(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_); + rtt_controllers_.emplace_back(rtt); + return {createWifiStatus(WifiStatusCode::SUCCESS), rtt}; +} + +std::pair> WifiChip::getUsableChannelsInternal_1_6( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask) { + legacy_hal::wifi_error legacy_status; + std::vector legacy_usable_channels; + std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels( + hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band), + hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask), + hidl_struct_util::convertHidlUsableChannelFilterToLegacy(filterMask)); + + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_usable_channels; + if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(legacy_usable_channels, + &hidl_usable_channels)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels}; +} + +std::pair +WifiChip::getSupportedRadioCombinationsMatrixInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_radio_combination_matrix* legacy_matrix; + + std::tie(legacy_status, legacy_matrix) = + legacy_hal_.lock()->getSupportedRadioCombinationsMatrix(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + + V1_6::WifiRadioCombinationMatrix hidl_matrix; + if (!hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, + &hidl_matrix)) { + LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToHidl() "; + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_matrix}; +} + +std::pair> +WifiChip::getAvailableModesInternal_1_6() { + return {createWifiStatus(WifiStatusCode::SUCCESS), modes_}; +} + +WifiStatus WifiChip::handleChipConfiguration( + /* NONNULL */ std::unique_lock* lock, ChipModeId mode_id) { + // If the chip is already configured in a different mode, stop + // the legacy HAL and then start it after firmware mode change. + if (isValidModeId(current_mode_id_)) { + LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id; + invalidateAndRemoveAllIfaces(); + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {}); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + } + // Firmware mode change not needed for V2 devices. + bool success = true; + if (mode_id == feature_flags::chip_mode_ids::kV1Sta) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); + } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP); + } + if (!success) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + // Every time the HAL is restarted, we need to register the + // radio mode change callback. + WifiStatus status = registerRadioModeChangeCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + // This probably is not a critical failure? + LOG(ERROR) << "Failed to register radio mode change callback"; + } + // Extract and save the version information into property. + std::pair version_info; + version_info = WifiChip::requestChipDebugInfoInternal(); + if (WifiStatusCode::SUCCESS == version_info.first.code) { + property_set("vendor.wlan.firmware.version", + version_info.second.firmwareDescription.c_str()); + property_set("vendor.wlan.driver.version", version_info.second.driverDescription.c_str()); + } + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::registerDebugRingBufferCallback() { + if (debug_ring_buffer_cb_registered_) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } + + android::wp weak_ptr_this(this); + const auto& on_ring_buffer_data_callback = + [weak_ptr_this](const std::string& name, const std::vector& data, + const legacy_hal::wifi_ring_buffer_status& status) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiDebugRingBufferStatus hidl_status; + Ringbuffer::AppendStatus appendstatus; + if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(status, + &hidl_status)) { + LOG(ERROR) << "Error converting ring buffer status"; + return; + } + { + std::unique_lock lk(shared_ptr_this->lock_t); + const auto& target = shared_ptr_this->ringbuffer_map_.find(name); + if (target != shared_ptr_this->ringbuffer_map_.end()) { + Ringbuffer& cur_buffer = target->second; + appendstatus = cur_buffer.append(data); + } else { + LOG(ERROR) << "Ringname " << name << " not found"; + return; + } + // unique_lock unlocked here + } + if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) { + LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer"; + shared_ptr_this->writeRingbufferFilesInternal(); + return; + } + + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler( + getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback); + + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = true; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerRadioModeChangeCallback() { + android::wp weak_ptr_this(this); + const auto& on_radio_mode_change_callback = + [weak_ptr_this](const std::vector& mac_infos) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector hidl_radio_mode_infos; + if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(mac_infos, + &hidl_radio_mode_infos)) { + LOG(ERROR) << "Error converting wifi mac info"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos).isOk()) { + LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4" + << " callback on: " << toString(callback); + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->registerRadioModeChangeCallbackHandler( + getFirstActiveWlanIfaceName(), on_radio_mode_change_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::vector +WifiChip::getCurrentModeConcurrencyCombinations() { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return {}; + } + for (const auto& mode : modes_) { + if (mode.id == current_mode_id_) { + return mode.availableCombinations; + } + } + CHECK(0) << "Expected to find concurrency combinations for current mode!"; + return {}; +} + +// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently +// created of the corresponding concurrency type. +std::map WifiChip::getCurrentConcurrencyCombination() { + std::map iface_counts; + uint32_t num_ap = 0; + uint32_t num_ap_bridged = 0; + for (const auto& ap_iface : ap_ifaces_) { + std::string ap_iface_name = ap_iface->getName(); + if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 && + br_ifaces_ap_instances_[ap_iface_name].size() > 1) { + num_ap_bridged++; + } else { + num_ap++; + } + } + iface_counts[IfaceConcurrencyType::AP] = num_ap; + iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged; + iface_counts[IfaceConcurrencyType::NAN] = nan_ifaces_.size(); + iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size(); + iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size(); + return iface_counts; +} + +// This expands the provided concurrency combinations to a more parseable +// form. Returns a vector of available combinations possible with the number +// of each concurrency type in the combination. +// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework. +std::vector> WifiChip::expandConcurrencyCombinations( + const V1_6::IWifiChip::ChipConcurrencyCombination& combination) { + uint32_t num_expanded_combos = 1; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + num_expanded_combos *= limit.types.size(); + } + } + + // Allocate the vector of expanded combos and reset all concurrency type counts to 0 + // in each combo. + std::vector> expanded_combos; + expanded_combos.resize(num_expanded_combos); + for (auto& expanded_combo : expanded_combos) { + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + expanded_combo[type] = 0; + } + } + uint32_t span = num_expanded_combos; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + span /= limit.types.size(); + for (uint32_t k = 0; k < num_expanded_combos; ++k) { + const auto iface_type = limit.types[(k / span) % limit.types.size()]; + expanded_combos[k][iface_type]++; + } + } + } + return expanded_combos; +} + +bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes( + const std::map& expanded_combo, + IfaceConcurrencyType requested_type) { + const auto current_combo = getCurrentConcurrencyCombination(); + + // Check if we have space for 1 more iface of |type| in this combo + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + size_t num_ifaces_needed = current_combo.at(type); + if (type == requested_type) { + num_ifaces_needed++; + } + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} + +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency type can be added to the current mode +// with the concurrency combination that is already active. +bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes( + IfaceConcurrencyType requested_type) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeConcurrencyCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandConcurrencyCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo, + requested_type)) { + return true; + } + } + } + return false; +} + +// Note: This does not consider concurrency types already active. It only checks if the +// provided expanded concurrency combination can support the requested combo. +bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo( + const std::map& expanded_combo, + const std::map& req_combo) { + // Check if we have space for 1 more |type| in this combo + for (const auto type : + {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN, + IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) { + if (req_combo.count(type) == 0) { + // Concurrency type not in the req_combo. + continue; + } + size_t num_ifaces_needed = req_combo.at(type); + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency combo can be added to the current mode. +// Note: This does not consider concurrency types already active. It only checks if the +// current mode can support the requested combo. +bool WifiChip::canCurrentModeSupportConcurrencyCombo( + const std::map& req_combo) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeConcurrencyCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandConcurrencyCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) { + return true; + } + } + } + return false; +} + +// This method does the following: +// a) Enumerate all possible concurrency combos by expanding the current +// ChipConcurrencyCombination. +// b) Check if the requested concurrency type can be added to the current mode. +bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) { + // Check if we can support at least 1 of the requested concurrency type. + std::map req_iface_combo; + req_iface_combo[requested_type] = 1; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +bool WifiChip::isValidModeId(ChipModeId mode_id) { + for (const auto& mode : modes_) { + if (mode.id == mode_id) { + return true; + } + } + return false; +} + +bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { + // Check if we can support at least 1 STA & 1 AP concurrently. + std::map req_iface_combo; + req_iface_combo[IfaceConcurrencyType::STA] = 1; + req_iface_combo[IfaceConcurrencyType::AP] = 1; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() { + // Check if we can support at least 2 STA concurrently. + std::map req_iface_combo; + req_iface_combo[IfaceConcurrencyType::STA] = 2; + return canCurrentModeSupportConcurrencyCombo(req_iface_combo); +} + +std::string WifiChip::getFirstActiveWlanIfaceName() { + if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); + if (ap_ifaces_.size() > 0) { + // If the first active wlan iface is bridged iface. + // Return first instance name. + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == ap_ifaces_[0]->getName()) { + return it.second[0]; + } + } + return ap_ifaces_[0]->getName(); + } + // This could happen if the chip call is made before any STA/AP + // iface is created. Default to wlan0 for such cases. + LOG(WARNING) << "No active wlan interfaces in use! Using default"; + return getWlanIfaceNameWithType(IfaceType::STA, 0); +} + +// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| +// not already in use. +// Note: This doesn't check the actual presence of these interfaces. +std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) { + for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) { + const auto ifname = getWlanIfaceNameWithType(type, idx); + if (findUsingNameFromBridgedApInstances(ifname)) continue; + if (findUsingName(ap_ifaces_, ifname)) continue; + if (findUsingName(sta_ifaces_, ifname)) continue; + return ifname; + } + // This should never happen. We screwed up somewhere if it did. + CHECK(false) << "All wlan interfaces in use already!"; + return {}; +} + +uint32_t WifiChip::startIdxOfApIface() { + if (isDualStaConcurrencyAllowedInCurrentMode()) { + // When the HAL support dual STAs, AP should start with idx 2. + return 2; + } else if (isStaApConcurrencyAllowedInCurrentMode()) { + // When the HAL support STA + AP but it doesn't support dual STAs. + // AP should start with idx 1. + return 1; + } + // No concurrency support. + return 0; +} + +// AP iface names start with idx 1 for modes supporting +// concurrent STA, else start with idx 0. +std::string WifiChip::allocateApIfaceName() { + // Check if we have a dedicated iface for AP. + std::vector ifnames = getPredefinedApIfaceNames(true); + for (auto const& ifname : ifnames) { + if (findUsingName(ap_ifaces_, ifname)) continue; + return ifname; + } + return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface()); +} + +std::vector WifiChip::allocateBridgedApInstanceNames() { + // Check if we have a dedicated iface for AP. + std::vector instances = getPredefinedApIfaceNames(true); + if (instances.size() == 2) { + return instances; + } else { + int num_ifaces_need_to_allocate = 2 - instances.size(); + for (int i = 0; i < num_ifaces_need_to_allocate; i++) { + std::string instance_name = + allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i); + if (!instance_name.empty()) { + instances.push_back(instance_name); + } + } + } + return instances; +} + +// STA iface names start with idx 0. +// Primary STA iface will always be 0. +std::string WifiChip::allocateStaIfaceName() { + return allocateApOrStaIfaceName(IfaceType::STA, 0); +} + +bool WifiChip::writeRingbufferFilesInternal() { + if (!removeOldFilesInternal()) { + LOG(ERROR) << "Error occurred while deleting old tombstone files"; + return false; + } + // write ringbuffers to file + { + std::unique_lock lk(lock_t); + for (auto& item : ringbuffer_map_) { + Ringbuffer& cur_buffer = item.second; + if (cur_buffer.getData().empty()) { + continue; + } + const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX"; + const int dump_fd = mkstemp(makeCharVec(file_path_raw).data()); + if (dump_fd == -1) { + PLOG(ERROR) << "create file failed"; + return false; + } + unique_fd file_auto_closer(dump_fd); + for (const auto& cur_block : cur_buffer.getData()) { + if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) { + PLOG(ERROR) << "Ring buffer: " << item.first + << " is corrupted. Invalid block size: " << cur_block.size(); + break; + } + if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) == + -1) { + PLOG(ERROR) << "Error writing to file"; + } + } + cur_buffer.clear(); + } + // unique_lock unlocked here + } + return true; +} + +std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) { + std::string ifname; + + // let the legacy hal override the interface name + legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname); + if (err == legacy_hal::WIFI_SUCCESS) return ifname; + + return getWlanIfaceName(idx); +} + +void WifiChip::invalidateAndClearBridgedApAll() { + for (auto const& it : br_ifaces_ap_instances_) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(it.first, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(it.first); + } + br_ifaces_ap_instances_.clear(); +} + +void WifiChip::deleteApIface(const std::string& if_name) { + if (if_name.empty()) return; + // delete bridged interfaces if have + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == if_name) { + for (auto const& iface : it.second) { + iface_util_->removeIfaceFromBridge(if_name, iface); + legacy_hal_.lock()->deleteVirtualInterface(iface); + } + iface_util_->deleteBridge(if_name); + br_ifaces_ap_instances_.erase(if_name); + // ifname is bridged AP, return here. + return; + } + } + + // No bridged AP case, delete AP iface + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(if_name); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to remove interface: " << if_name << " " + << legacyErrorToString(legacy_status); + } +} + +bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) { + for (auto const& it : br_ifaces_ap_instances_) { + if (it.first == name) { + return true; + } + for (auto const& iface : it.second) { + if (iface == name) { + return true; + } + } + } + return false; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h new file mode 100644 index 0000000..27baf3d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_chip.h @@ -0,0 +1,322 @@ +/* + * 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 WIFI_CHIP_H_ +#define WIFI_CHIP_H_ + +// HACK: NAN is a macro defined in math.h, which can be included in various +// headers. This wifi HAL uses an enum called NAN, which does not compile when +// the macro is defined. Undefine NAN to work around it. +#undef NAN + +#include +#include +#include + +#include +#include +#include +#include + +#include "hidl_callback_util.h" +#include "ringbuffer.h" +#include "wifi_ap_iface.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" +#include "wifi_nan_iface.h" +#include "wifi_p2p_iface.h" +#include "wifi_rtt_controller.h" +#include "wifi_sta_iface.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; +using V1_5::WifiBand; + +/** + * HIDL interface object used to control a Wifi HAL chip instance. + * Since there is only a single chip instance used today, there is no + * identifying handle information stored here. + */ +class WifiChip : public V1_6::IWifiChip { + public: + WifiChip(ChipId chip_id, bool is_primary, + const std::weak_ptr legacy_hal, + const std::weak_ptr mode_controller, + const std::shared_ptr iface_util, + const std::weak_ptr feature_flags, + const std::function& subsystemCallbackHandler); + // HIDL does not provide a built-in mechanism to let the server invalidate + // a HIDL interface object after creation. If any client process holds onto + // a reference to the object in their context, any method calls on that + // reference will continue to be directed to the server. + // + // However Wifi HAL needs to control the lifetime of these objects. So, add + // a public |invalidate| method to |WifiChip| and it's child objects. This + // will be used to mark an object invalid when either: + // a) Wifi HAL is stopped, or + // b) Wifi Chip is reconfigured. + // + // All HIDL method implementations should check if the object is still + // marked valid before processing them. + void invalidate(); + bool isValid(); + std::set> getEventCallbacks(); + + // HIDL methods exposed. + Return getId(getId_cb hidl_status_cb) override; + // Deprecated support for this callback + Return registerEventCallback(const sp& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return getAvailableModes(getAvailableModes_cb hidl_status_cb) override; + Return configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) override; + Return getMode(getMode_cb hidl_status_cb) override; + Return requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) override; + Return requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) override; + Return requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) override; + Return createApIface(createApIface_cb hidl_status_cb) override; + Return createBridgedApIface(createBridgedApIface_cb hidl_status_cb) override; + Return getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; + Return getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override; + Return removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override; + Return removeIfaceInstanceFromBridgedApIface( + const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override; + Return createNanIface(createNanIface_cb hidl_status_cb) override; + Return getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; + Return getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) override; + Return removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) override; + Return createP2pIface(createP2pIface_cb hidl_status_cb) override; + Return getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override; + Return getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) override; + Return removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) override; + Return createStaIface(createStaIface_cb hidl_status_cb) override; + Return getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override; + Return getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) override; + Return removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) override; + Return createRttController(const sp& bound_iface, + createRttController_cb hidl_status_cb) override; + Return getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) override; + Return startLoggingToDebugRingBuffer( + const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return forceDumpToDebugRingBuffer(const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) override; + Return flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) override; + Return stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) override; + Return enableDebugErrorAlerts(bool enable, + enableDebugErrorAlerts_cb hidl_status_cb) override; + Return selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) override; + Return setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) override; + Return registerEventCallback_1_2(const sp& event_callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return selectTxPowerScenario_1_2(TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return getCapabilities_1_3(getCapabilities_cb hidl_status_cb) override; + Return getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) override; + Return debug(const hidl_handle& handle, const hidl_vec& options) override; + Return createRttController_1_4(const sp& bound_iface, + createRttController_1_4_cb hidl_status_cb) override; + Return registerEventCallback_1_4(const sp& event_callback, + registerEventCallback_1_4_cb hidl_status_cb) override; + Return setMultiStaPrimaryConnection( + const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) override; + Return setMultiStaUseCase(MultiStaUseCase use_case, + setMultiStaUseCase_cb hidl_status_cb) override; + Return setCoexUnsafeChannels(const hidl_vec& unsafe_channels, + hidl_bitfield restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) override; + Return setCountryCode(const hidl_array& code, + setCountryCode_cb _hidl_cb) override; + Return getUsableChannels(WifiBand band, hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_cb _hidl_cb) override; + Return triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) override; + Return createRttController_1_6(const sp& bound_iface, + createRttController_1_6_cb hidl_status_cb) override; + Return getUsableChannels_1_6(WifiBand band, + hidl_bitfield ifaceModeMask, + hidl_bitfield filterMask, + getUsableChannels_1_6_cb _hidl_cb) override; + Return getSupportedRadioCombinationsMatrix( + getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override; + Return getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) override; + + private: + void invalidateAndRemoveAllIfaces(); + // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are + // invalidated & removed. + void invalidateAndRemoveDependencies(const std::string& removed_iface_name); + + // Corresponding worker functions for the HIDL methods. + std::pair getIdInternal(); + // Deprecated support for this callback + WifiStatus registerEventCallbackInternal( + const sp& event_callback); + std::pair getCapabilitiesInternal(); + std::pair> getAvailableModesInternal(); + WifiStatus configureChipInternal(std::unique_lock* lock, + ChipModeId mode_id); + std::pair getModeInternal(); + std::pair requestChipDebugInfoInternal(); + std::pair> requestDriverDebugDumpInternal(); + std::pair> requestFirmwareDebugDumpInternal(); + sp newWifiApIface(std::string& ifname); + WifiStatus createVirtualApInterface(const std::string& apVirtIf); + std::pair> createApIfaceInternal(); + std::pair> createBridgedApIfaceInternal(); + std::pair> getApIfaceNamesInternal(); + std::pair> getApIfaceInternal(const std::string& ifname); + WifiStatus removeApIfaceInternal(const std::string& ifname); + WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(const std::string& brIfaceName, + const std::string& ifInstanceName); + std::pair> createNanIfaceInternal(); + std::pair> getNanIfaceNamesInternal(); + std::pair> getNanIfaceInternal(const std::string& ifname); + WifiStatus removeNanIfaceInternal(const std::string& ifname); + std::pair> createP2pIfaceInternal(); + std::pair> getP2pIfaceNamesInternal(); + std::pair> getP2pIfaceInternal(const std::string& ifname); + WifiStatus removeP2pIfaceInternal(const std::string& ifname); + std::pair> createStaIfaceInternal(); + std::pair> getStaIfaceNamesInternal(); + std::pair> getStaIfaceInternal(const std::string& ifname); + WifiStatus removeStaIfaceInternal(const std::string& ifname); + std::pair> createRttControllerInternal( + const sp& bound_iface); + std::pair> + getDebugRingBuffersStatusInternal(); + WifiStatus startLoggingToDebugRingBufferInternal(const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, + uint32_t min_data_size_in_bytes); + WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name); + WifiStatus flushRingBufferToFileInternal(); + WifiStatus stopLoggingToDebugRingBufferInternal(); + std::pair getDebugHostWakeReasonStatsInternal(); + WifiStatus enableDebugErrorAlertsInternal(bool enable); + WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario); + WifiStatus resetTxPowerScenarioInternal(); + WifiStatus setLatencyModeInternal(LatencyMode mode); + WifiStatus registerEventCallbackInternal_1_2( + const sp& event_callback); + WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario); + std::pair getCapabilitiesInternal_1_3(); + std::pair getCapabilitiesInternal_1_5(); + std::pair> createRttControllerInternal_1_4( + const sp& bound_iface); + WifiStatus registerEventCallbackInternal_1_4( + const sp& event_callback); + WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname); + WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case); + WifiStatus setCoexUnsafeChannelsInternal(std::vector unsafe_channels, + uint32_t restrictions); + WifiStatus setCountryCodeInternal(const std::array& code); + std::pair> getUsableChannelsInternal( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask); + WifiStatus handleChipConfiguration(std::unique_lock* lock, + ChipModeId mode_id); + WifiStatus registerDebugRingBufferCallback(); + WifiStatus registerRadioModeChangeCallback(); + std::vector + getCurrentModeConcurrencyCombinations(); + std::map getCurrentConcurrencyCombination(); + std::vector> expandConcurrencyCombinations( + const V1_6::IWifiChip::ChipConcurrencyCombination& combination); + bool canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes( + const std::map& expanded_combo, + IfaceConcurrencyType requested_type); + bool canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType requested_type); + bool canExpandedConcurrencyComboSupportConcurrencyCombo( + const std::map& expanded_combo, + const std::map& req_combo); + bool canCurrentModeSupportConcurrencyCombo( + const std::map& req_combo); + bool canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type); + bool isValidModeId(ChipModeId mode_id); + bool isStaApConcurrencyAllowedInCurrentMode(); + bool isDualStaConcurrencyAllowedInCurrentMode(); + uint32_t startIdxOfApIface(); + std::string getFirstActiveWlanIfaceName(); + std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx); + std::string allocateApIfaceName(); + std::vector allocateBridgedApInstanceNames(); + std::string allocateStaIfaceName(); + bool writeRingbufferFilesInternal(); + std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx); + void invalidateAndClearBridgedApAll(); + void deleteApIface(const std::string& if_name); + bool findUsingNameFromBridgedApInstances(const std::string& name); + WifiStatus triggerSubsystemRestartInternal(); + void QcRemoveAndClearDynamicIfaces(); + std::pair> createRttControllerInternal_1_6( + const sp& bound_iface); + std::pair> getUsableChannelsInternal_1_6( + WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask); + std::pair getSupportedRadioCombinationsMatrixInternal(); + std::pair> getAvailableModesInternal_1_6(); + + ChipId chip_id_; + std::weak_ptr legacy_hal_; + std::weak_ptr mode_controller_; + std::shared_ptr iface_util_; + std::vector> ap_ifaces_; + std::vector> nan_ifaces_; + std::vector> p2p_ifaces_; + std::vector> sta_ifaces_; + std::vector> rtt_controllers_; + std::map ringbuffer_map_; + bool is_valid_; + // Members pertaining to chip configuration. + uint32_t current_mode_id_; + std::mutex lock_t; + std::vector modes_; + // The legacy ring buffer callback API has only a global callback + // registration mechanism. Use this to check if we have already + // registered a callback. + bool debug_ring_buffer_cb_registered_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + + const std::function subsystemCallbackHandler_; + std::map> br_ifaces_ap_instances_; + + std::vector> created_ap_ifaces_; + std::vector> created_sta_ifaces_; + + DISALLOW_COPY_AND_ASSIGN(WifiChip); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_CHIP_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp new file mode 100644 index 0000000..e80a3cd --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "wifi_feature_flags.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace feature_flags { + +using V1_0::ChipModeId; +using V1_0::IWifiChip; +using V1_6::IfaceConcurrencyType; + +/* The chip may either have a single mode supporting any number of combinations, + * or a fixed dual-mode (so it involves firmware loading to switch between + * modes) setting. If there is a need to support more modes, it needs to be + * implemented manually in WiFi HAL (see changeFirmwareMode in + * WifiChip::handleChipConfiguration). + * + * Supported combinations are defined in device's makefile, for example: + * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}}, + * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}} + * What means: + * Interface concurrency combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface + * operations. + * Interface concurrency combination 2: 1 STA and 2 AP concurrent iface operations. + * + * For backward compatibility, the following makefile flags can be used to + * generate combinations list: + * - WIFI_HIDL_FEATURE_DUAL_INTERFACE + * - WIFI_HIDL_FEATURE_DISABLE_AP + * - WIFI_HIDL_FEATURE_AWARE + * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided. + * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with + * two concurrency combinations: + * Interface Concurrency Combination 1: Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Interface Concurrency Combination 2: Will support 1 STA and 1 AP concurrent + * iface operations. + * + * The only dual-mode configuration supported is for alternating STA and AP + * mode, that may involve firmware reloading. In such case, there are 2 separate + * modes of operation with 1 concurrency combination each: + * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Mode 2 (AP mode): Will support 1 AP iface operation. + * + * If Aware is enabled, the concurrency combination will be modified to support either + * P2P or NAN in place of just P2P. + */ +// clang-format off +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE) +// former V2 (fixed dual interface) setup expressed as V3 +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +# ifdef WIFI_HIDL_FEATURE_DISABLE_AP +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif +# else +# ifdef WIFI_HIDL_FEATURE_AWARE +// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// (1 STA + 1 AP) or (1 STA + 1 P2P) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P}, 1}} +# endif +# endif +#else +// V1 (fixed single interface, dual-mode chip) +constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta; +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif + +# ifndef WIFI_HIDL_FEATURE_DISABLE_AP +# define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}} +# endif +#endif +// clang-format on + +/** + * Helper class to convert a collection of combination limits to a combination. + * + * The main point here is to simplify the syntax required by + * WIFI_HAL_INTERFACE_COMBINATIONS. + */ +struct ChipConcurrencyCombination + : public hidl_vec { + ChipConcurrencyCombination( + const std::initializer_list list) + : hidl_vec(list) {} + + operator V1_6::IWifiChip::ChipConcurrencyCombination() const { return {*this}; } + + static hidl_vec make_vec( + const std::initializer_list list) { + return hidl_vec( // + std::begin(list), std::end(list)); + } +}; + +#define STA IfaceConcurrencyType::STA +#define AP IfaceConcurrencyType::AP +#define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED +#define P2P IfaceConcurrencyType::P2P +#define NAN IfaceConcurrencyType::NAN +static const std::vector kChipModesPrimary{ + {kMainModeId, ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})}, +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP + {chip_mode_ids::kV1Ap, + ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})}, +#endif +}; + +static const std::vector kChipModesSecondary{ +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP + {chip_mode_ids::kV3, + ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})}, +#endif +}; + +constexpr char kDebugPresetInterfaceCombinationIdxProperty[] = + "persist.vendor.debug.wifi.hal.preset_interface_combination_idx"; +// List of pre-defined concurrency combinations that can be enabled at runtime via +// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the +// corresponding index value. +static const std::vector>> + kDebugChipModes{// Legacy combination - No STA/AP concurrencies. + // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN)) + {"No STA/AP Concurrency", + {{kMainModeId, ChipConcurrencyCombination::make_vec( + {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + AP concurrency + // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) + {"STA + AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency + // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}, + + // AP + AP + STA concurrency + // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN)) + {"Dual AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency and AP + AP + STA concurrency + // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN)) + {"Dual STA & Dual AP Concurrency", + {{kMainModeId, + ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}, + + // STA + STA concurrency + // 5 - (1 STA + 1 AP (bridged or single) | P2P | NAN), or (2 STA)) + {"Dual STA or STA plus single other interface", + {{kMainModeId, ChipConcurrencyCombination::make_vec( + {{{{STA}, 1}, {{P2P, NAN, AP, AP_BRIDGED}, 1}}, + {{{STA}, 2}}})}}}}; + +#undef STA +#undef AP +#undef P2P +#undef NAN + +#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +#pragma message \ + "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \ + "'config_wifi_ap_randomization_supported' in " \ + "frameworks/base/core/res/res/values/config.xml in the device overlay " \ + "instead" +#endif // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION + +WifiFeatureFlags::WifiFeatureFlags() {} + +std::vector WifiFeatureFlags::getChipModesForPrimary() { + std::array buffer; + auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, buffer.data(), nullptr); + // Debug property not set, use the device preset concurrency combination. + if (res <= 0) return kChipModesPrimary; + + // Debug property set, use one of the debug preset concurrency combination. + unsigned long idx = std::stoul(buffer.data()); + if (idx >= kDebugChipModes.size()) { + LOG(ERROR) << "Invalid index set in property: " + << kDebugPresetInterfaceCombinationIdxProperty; + return kChipModesPrimary; + } + std::string name; + std::vector chip_modes; + std::tie(name, chip_modes) = kDebugChipModes[idx]; + LOG(INFO) << "Using debug chip mode: <" << name + << "> set via property: " << kDebugPresetInterfaceCombinationIdxProperty; + return chip_modes; +} + +std::vector WifiFeatureFlags::getChipModes(bool is_primary) { + return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary; +} + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h new file mode 100644 index 0000000..1635341 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_feature_flags.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WIFI_FEATURE_FLAGS_H_ +#define WIFI_FEATURE_FLAGS_H_ + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace feature_flags { + +namespace chip_mode_ids { +// These mode ID's should be unique (even across combo versions). Refer to +// handleChipConfiguration() for it's usage. +constexpr V1_0::ChipModeId kInvalid = UINT32_MAX; +// Mode ID's for V1 +constexpr V1_0::ChipModeId kV1Sta = 0; +constexpr V1_0::ChipModeId kV1Ap = 1; +// Mode ID for V3 +constexpr V1_0::ChipModeId kV3 = 3; +} // namespace chip_mode_ids + +class WifiFeatureFlags { + public: + WifiFeatureFlags(); + virtual ~WifiFeatureFlags() = default; + + virtual std::vector getChipModes(bool is_primary); + + private: + std::vector getChipModesForPrimary(); +}; + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_FEATURE_FLAGS_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp new file mode 100644 index 0000000..d55e4f8 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#undef NAN +#include "wifi_iface_util.h" + +namespace { +// Constants to set the local bit & clear the multicast bit. +constexpr uint8_t kMacAddressMulticastMask = 0x01; +constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace iface_util { + +WifiIfaceUtil::WifiIfaceUtil(const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal) + : iface_tool_(iface_tool), + legacy_hal_(legacy_hal), + random_mac_address_(nullptr), + event_handlers_map_() {} + +std::array WifiIfaceUtil::getFactoryMacAddress(const std::string& iface_name) { + return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str()); +} + +bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, + const std::array& mac) { +#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(iface_name); + + if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) && + !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) { + LOG(ERROR) << "SetUpState(false) failed."; + return false; + } +#endif + bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac); +#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE + if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) && + !iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready."; + // Wait for driver ready and try to set iface UP again + if (legacy_hal_.lock()->waitForDriverReady() != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "SetUpState(true) wait for driver ready failed."; + return false; + } + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed after retry."; + return false; + } + } +#endif + IfaceEventHandlers event_handlers = {}; + const auto it = event_handlers_map_.find(iface_name); + if (it != event_handlers_map_.end()) { + event_handlers = it->second; + } + if (event_handlers.on_state_toggle_off_on != nullptr) { + event_handlers.on_state_toggle_off_on(iface_name); + } + if (!success) { + LOG(ERROR) << "SetMacAddress failed on " << iface_name; + } else { + LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name; + } + return success; +} + +std::array WifiIfaceUtil::getOrCreateRandomMacAddress() { + if (random_mac_address_) { + return *random_mac_address_.get(); + } + random_mac_address_ = std::make_unique>(createRandomMacAddress()); + return *random_mac_address_.get(); +} + +void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers) { + event_handlers_map_[iface_name] = handlers; +} + +void WifiIfaceUtil::unregisterIfaceEventHandlers(const std::string& iface_name) { + event_handlers_map_.erase(iface_name); +} + +std::array WifiIfaceUtil::createRandomMacAddress() { + std::array address = {}; + std::random_device rd; + std::default_random_engine engine(rd()); + std::uniform_int_distribution dist(std::numeric_limits::min(), + std::numeric_limits::max()); + for (size_t i = 0; i < address.size(); i++) { + address[i] = dist(engine); + } + // Set the local bit and clear the multicast bit. + address[0] |= kMacAddressLocallyAssignedMask; + address[0] &= ~kMacAddressMulticastMask; + return address; +} + +bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) { + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) { + LOG(ERROR) << "SetUpState to " << request_up << " failed"; + return false; + } + return true; +} + +unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) { + return if_nametoindex(iface_name.c_str()); +} + +bool WifiIfaceUtil::createBridge(const std::string& br_name) { + if (!iface_tool_.lock()->createBridge(br_name)) { + return false; + } + + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), true)) { + LOG(ERROR) << "bridge SetUpState(true) failed."; + } + return true; +} + +bool WifiIfaceUtil::deleteBridge(const std::string& br_name) { + if (!iface_tool_.lock()->SetUpState(br_name.c_str(), false)) { + LOG(INFO) << "SetUpState(false) failed for bridge=" << br_name.c_str(); + } + + return iface_tool_.lock()->deleteBridge(br_name); +} + +bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, const std::string& if_name) { + return iface_tool_.lock()->addIfaceToBridge(br_name, if_name); +} + +bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) { + return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name); +} + +} // namespace iface_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h new file mode 100644 index 0000000..c5db5de --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_iface_util.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 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 WIFI_IFACE_UTIL_H_ +#define WIFI_IFACE_UTIL_H_ + +#include + +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace iface_util { + +// Iface event handlers. +struct IfaceEventHandlers { + // Callback to be invoked when the iface is set down & up for MAC address + // change. + std::function on_state_toggle_off_on; +}; + +/** + * Util class for common iface operations. + */ +class WifiIfaceUtil { + public: + WifiIfaceUtil(const std::weak_ptr iface_tool, + const std::weak_ptr legacy_hal); + virtual ~WifiIfaceUtil() = default; + + virtual std::array getFactoryMacAddress(const std::string& iface_name); + virtual bool setMacAddress(const std::string& iface_name, const std::array& mac); + // Get or create a random MAC address. The MAC address returned from + // this method will remain the same throughout the lifetime of the HAL + // daemon. (So, changes on every reboot) + virtual std::array getOrCreateRandomMacAddress(); + + // Register for any iface event callbacks for the provided interface. + virtual void registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers); + virtual void unregisterIfaceEventHandlers(const std::string& iface_name); + virtual bool setUpState(const std::string& iface_name, bool request_up); + virtual unsigned ifNameToIndex(const std::string& iface_name); + + virtual bool createBridge(const std::string& br_name); + + virtual bool deleteBridge(const std::string& br_name); + + virtual bool addIfaceToBridge(const std::string& br_name, const std::string& if_name); + + virtual bool removeIfaceFromBridge(const std::string& br_name, const std::string& if_name); + // Get a random MAC address. + virtual std::array createRandomMacAddress(); + + private: + std::weak_ptr iface_tool_; + std::weak_ptr legacy_hal_; + std::unique_ptr> random_mac_address_; + std::map event_handlers_map_; +}; + +} // namespace iface_util +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_IFACE_UTIL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp new file mode 100644 index 0000000..43cb7c4 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.cpp @@ -0,0 +1,1654 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include + +#include "hidl_sync_util.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +// Constants ported over from the legacy HAL calling code +// (com_android_server_wifi_WifiNative.cpp). This will all be thrown +// away when this shim layer is replaced by the real vendor +// implementation. +static constexpr uint32_t kMaxVersionStringLength = 256; +static constexpr uint32_t kMaxCachedGscanResults = 64; +static constexpr uint32_t kMaxGscanFrequenciesForBand = 64; +static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128; +static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32; +static constexpr uint32_t kMaxRingBuffers = 10; +static constexpr uint32_t kMaxWifiUsableChannels = 256; +static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256; +// need a long timeout (1000ms) for chips that unload their driver. +static constexpr uint32_t kMaxStopCompleteWaitMs = 1000; +static constexpr char kDriverPropName[] = "wlan.driver.status"; + +// Helper function to create a non-const char* for legacy Hal API's. +std::vector makeCharVec(const std::string& str) { + std::vector vec(str.size() + 1); + vec.assign(str.begin(), str.end()); + vec.push_back('\0'); + return vec; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { + +// Legacy HAL functions accept "C" style function pointers, so use global +// functions to pass to the legacy HAL function and store the corresponding +// std::function methods to be invoked. +// +// Callback to be invoked once |stop| is complete +std::function on_stop_complete_internal_callback; +void onAsyncStopComplete(wifi_handle handle) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_stop_complete_internal_callback) { + on_stop_complete_internal_callback(handle); + // Invalidate this callback since we don't want this firing again. + on_stop_complete_internal_callback = nullptr; + } +} + +// Callback to be invoked for driver dump. +std::function on_driver_memory_dump_internal_callback; +void onSyncDriverMemoryDump(char* buffer, int buffer_size) { + if (on_driver_memory_dump_internal_callback) { + on_driver_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for firmware dump. +std::function on_firmware_memory_dump_internal_callback; +void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) { + if (on_firmware_memory_dump_internal_callback) { + on_firmware_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for Gscan events. +std::function on_gscan_event_internal_callback; +void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_event_internal_callback) { + on_gscan_event_internal_callback(id, event); + } +} + +// Callback to be invoked for Gscan full results. +std::function + on_gscan_full_result_internal_callback; +void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_full_result_internal_callback) { + on_gscan_full_result_internal_callback(id, result, buckets_scanned); + } +} + +// Callback to be invoked for link layer stats results. +std::function + on_link_layer_stats_result_internal_callback; +void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios, + wifi_radio_stat* radio_stat) { + if (on_link_layer_stats_result_internal_callback) { + on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, radio_stat); + } +} + +// Callback to be invoked for rssi threshold breach. +std::function + on_rssi_threshold_breached_internal_callback; +void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rssi_threshold_breached_internal_callback) { + on_rssi_threshold_breached_internal_callback(id, bssid, rssi); + } +} + +// Callback to be invoked for ring buffer data indication. +std::function + on_ring_buffer_data_internal_callback; +void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_ring_buffer_data_internal_callback) { + on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, status); + } +} + +// Callback to be invoked for error alert indication. +std::function on_error_alert_internal_callback; +void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, int err_code) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_error_alert_internal_callback) { + on_error_alert_internal_callback(id, buffer, buffer_size, err_code); + } +} + +// Callback to be invoked for radio mode change indication. +std::function + on_radio_mode_change_internal_callback; +void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_radio_mode_change_internal_callback) { + on_radio_mode_change_internal_callback(id, num_macs, mac_infos); + } +} + +// Callback to be invoked to report subsystem restart +std::function on_subsystem_restart_internal_callback; +void onAsyncSubsystemRestart(const char* error) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_subsystem_restart_internal_callback) { + on_subsystem_restart_internal_callback(error); + } +} + +// Callback to be invoked for rtt results results. +std::function + on_rtt_results_internal_callback; +void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rtt_results_internal_callback) { + on_rtt_results_internal_callback(id, num_results, rtt_results); + on_rtt_results_internal_callback = nullptr; + } +} + +// Callbacks for the various NAN operations. +// NOTE: These have very little conversions to perform before invoking the user +// callbacks. +// So, handle all of them here directly to avoid adding an unnecessary layer. +std::function on_nan_notify_response_user_callback; +void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_notify_response_user_callback && msg) { + on_nan_notify_response_user_callback(id, *msg); + } +} + +std::function on_nan_event_publish_replied_user_callback; +void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) { + LOG(ERROR) << "onAysncNanEventPublishReplied triggered"; +} + +std::function on_nan_event_publish_terminated_user_callback; +void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_publish_terminated_user_callback && event) { + on_nan_event_publish_terminated_user_callback(*event); + } +} + +std::function on_nan_event_match_user_callback; +void onAysncNanEventMatch(NanMatchInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_user_callback && event) { + on_nan_event_match_user_callback(*event); + } +} + +std::function on_nan_event_match_expired_user_callback; +void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_expired_user_callback && event) { + on_nan_event_match_expired_user_callback(*event); + } +} + +std::function + on_nan_event_subscribe_terminated_user_callback; +void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_subscribe_terminated_user_callback && event) { + on_nan_event_subscribe_terminated_user_callback(*event); + } +} + +std::function on_nan_event_followup_user_callback; +void onAysncNanEventFollowup(NanFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_followup_user_callback && event) { + on_nan_event_followup_user_callback(*event); + } +} + +std::function on_nan_event_disc_eng_event_user_callback; +void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disc_eng_event_user_callback && event) { + on_nan_event_disc_eng_event_user_callback(*event); + } +} + +std::function on_nan_event_disabled_user_callback; +void onAysncNanEventDisabled(NanDisabledInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disabled_user_callback && event) { + on_nan_event_disabled_user_callback(*event); + } +} + +std::function on_nan_event_tca_user_callback; +void onAysncNanEventTca(NanTCAInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_tca_user_callback && event) { + on_nan_event_tca_user_callback(*event); + } +} + +std::function on_nan_event_beacon_sdf_payload_user_callback; +void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_beacon_sdf_payload_user_callback && event) { + on_nan_event_beacon_sdf_payload_user_callback(*event); + } +} + +std::function on_nan_event_data_path_request_user_callback; +void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_request_user_callback && event) { + on_nan_event_data_path_request_user_callback(*event); + } +} +std::function on_nan_event_data_path_confirm_user_callback; +void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_confirm_user_callback && event) { + on_nan_event_data_path_confirm_user_callback(*event); + } +} + +std::function on_nan_event_data_path_end_user_callback; +void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_end_user_callback && event) { + on_nan_event_data_path_end_user_callback(*event); + } +} + +std::function on_nan_event_transmit_follow_up_user_callback; +void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_transmit_follow_up_user_callback && event) { + on_nan_event_transmit_follow_up_user_callback(*event); + } +} + +std::function on_nan_event_range_request_user_callback; +void onAysncNanEventRangeRequest(NanRangeRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_request_user_callback && event) { + on_nan_event_range_request_user_callback(*event); + } +} + +std::function on_nan_event_range_report_user_callback; +void onAysncNanEventRangeReport(NanRangeReportInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_report_user_callback && event) { + on_nan_event_range_report_user_callback(*event); + } +} + +std::function on_nan_event_schedule_update_user_callback; +void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_schedule_update_user_callback && event) { + on_nan_event_schedule_update_user_callback(*event); + } +} + +// Callbacks for the various TWT operations. +std::function on_twt_event_setup_response_callback; +void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_setup_response_callback && event) { + on_twt_event_setup_response_callback(*event); + } +} + +std::function on_twt_event_teardown_completion_callback; +void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_teardown_completion_callback && event) { + on_twt_event_teardown_completion_callback(*event); + } +} + +std::function on_twt_event_info_frame_received_callback; +void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_info_frame_received_callback && event) { + on_twt_event_info_frame_received_callback(*event); + } +} + +std::function on_twt_event_device_notify_callback; +void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_twt_event_device_notify_callback && event) { + on_twt_event_device_notify_callback(*event); + } +} + +// Callback to report current CHRE NAN state +std::function on_chre_nan_rtt_internal_callback; +void onAsyncChreNanRttState(chre_nan_rtt_state state) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_chre_nan_rtt_internal_callback) { + on_chre_nan_rtt_internal_callback(state); + } +} + +// Callback to report cached scan results +std::function on_cached_scan_results_internal_callback; +void onSyncCachedScanResults(wifi_cached_scan_report* cache_report) { + if (on_cached_scan_results_internal_callback) { + on_cached_scan_results_internal_callback(cache_report); + } +} + +// End of the free-standing "C" style callbacks. + +WifiLegacyHal::WifiLegacyHal(const std::weak_ptr iface_tool, + const wifi_hal_fn& fn, bool is_primary) + : global_func_table_(fn), + global_handle_(nullptr), + awaiting_event_loop_termination_(false), + is_started_(false), + iface_tool_(iface_tool), + is_primary_(is_primary) {} + +wifi_error WifiLegacyHal::initialize() { + LOG(DEBUG) << "Initialize legacy HAL"; + // this now does nothing, since HAL function table is provided + // to the constructor + return WIFI_SUCCESS; +} + +wifi_error WifiLegacyHal::start() { + // Ensure that we're starting in a good state. + CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() && + !awaiting_event_loop_termination_); + if (is_started_) { + LOG(DEBUG) << "Legacy HAL already started"; + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Waiting for the driver ready"; + wifi_error status = global_func_table_.wifi_wait_for_driver_ready(); + if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) { + LOG(ERROR) << "Failed or timed out awaiting driver ready"; + return status; + } + + if (is_primary_) { + property_set(kDriverPropName, "ok"); + + if (!iface_tool_.lock()->SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } + } + + LOG(DEBUG) << "Starting legacy HAL"; + status = global_func_table_.wifi_initialize(&global_handle_); + if (status != WIFI_SUCCESS || !global_handle_) { + LOG(ERROR) << "Failed to retrieve global handle"; + return status; + } + std::thread(&WifiLegacyHal::runEventLoop, this).detach(); + status = retrieveIfaceHandles(); + if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) { + LOG(ERROR) << "Failed to retrieve wlan interface handle"; + return status; + } + LOG(DEBUG) << "Legacy HAL start complete"; + is_started_ = true; + return WIFI_SUCCESS; +} + +wifi_error WifiLegacyHal::stop( + /* NONNULL */ std::unique_lock* lock, + const std::function& on_stop_complete_user_callback) { + if (!is_started_) { + LOG(DEBUG) << "Legacy HAL already stopped"; + on_stop_complete_user_callback(); + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Stopping legacy HAL"; + on_stop_complete_internal_callback = [on_stop_complete_user_callback, + this](wifi_handle handle) { + CHECK_EQ(global_handle_, handle) << "Handle mismatch"; + LOG(INFO) << "Legacy HAL stop complete callback received"; + // Invalidate all the internal pointers now that the HAL is + // stopped. + invalidate(); + if (is_primary_) iface_tool_.lock()->SetWifiUpState(false); + on_stop_complete_user_callback(); + is_started_ = false; + }; + awaiting_event_loop_termination_ = true; + global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete); + const auto status = + stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs), + [this] { return !awaiting_event_loop_termination_; }); + if (!status) { + LOG(ERROR) << "Legacy HAL stop failed or timed out"; + return WIFI_ERROR_UNKNOWN; + } + LOG(DEBUG) << "Legacy HAL stop complete"; + return WIFI_SUCCESS; +} + +bool WifiLegacyHal::isStarted() { + return is_started_; +} + +wifi_error WifiLegacyHal::waitForDriverReady() { + return global_func_table_.wifi_wait_for_driver_ready(); +} + +std::pair WifiLegacyHal::getDriverVersion(const std::string& iface_name) { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name), + buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair WifiLegacyHal::getFirmwareVersion( + const std::string& iface_name) { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name), + buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair> WifiLegacyHal::requestDriverMemoryDump( + const std::string& iface_name) { + std::vector driver_dump; + on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) { + driver_dump.insert(driver_dump.end(), reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name), + {onSyncDriverMemoryDump}); + on_driver_memory_dump_internal_callback = nullptr; + return {status, std::move(driver_dump)}; +} + +std::pair> WifiLegacyHal::requestFirmwareMemoryDump( + const std::string& iface_name) { + std::vector firmware_dump; + on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) { + firmware_dump.insert(firmware_dump.end(), reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_firmware_memory_dump( + getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump}); + on_firmware_memory_dump_internal_callback = nullptr; + return {status, std::move(firmware_dump)}; +} + +std::pair WifiLegacyHal::getSupportedFeatureSet( + const std::string& iface_name) { + feature_set set = 0, chip_set = 0; + wifi_error status = WIFI_SUCCESS; + + static_assert(sizeof(set) == sizeof(uint64_t), + "Some feature_flags can not be represented in output"); + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + global_func_table_.wifi_get_chip_feature_set( + global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */ + + if (iface_handle) { + status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set); + } + return {status, static_cast(set | chip_set)}; +} + +std::pair WifiLegacyHal::getPacketFilterCapabilities( + const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + return {status, caps}; +} + +wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name, + const std::vector& program) { + return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(), + program.size()); +} + +std::pair> WifiLegacyHal::readApfPacketFilterData( + const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + if (status != WIFI_SUCCESS) { + return {status, {}}; + } + + // Size the buffer to read the entire program & work memory. + std::vector buffer(caps.max_len); + + status = global_func_table_.wifi_read_packet_filter( + getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size()); + return {status, std::move(buffer)}; +} + +std::pair WifiLegacyHal::getGscanCapabilities( + const std::string& iface_name) { + wifi_gscan_capabilities caps; + wifi_error status = + global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::startGscan( + const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params, + const std::function& on_failure_user_callback, + const on_gscan_results_callback& on_results_user_callback, + const on_gscan_full_result_callback& on_full_result_user_callback) { + // If there is already an ongoing background scan, reject new scan requests. + if (on_gscan_event_internal_callback || on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + // This callback will be used to either trigger |on_results_user_callback| + // or |on_failure_user_callback|. + on_gscan_event_internal_callback = [iface_name, on_failure_user_callback, + on_results_user_callback, + this](wifi_request_id id, wifi_scan_event event) { + switch (event) { + case WIFI_SCAN_RESULTS_AVAILABLE: + case WIFI_SCAN_THRESHOLD_NUM_SCANS: + case WIFI_SCAN_THRESHOLD_PERCENT: { + wifi_error status; + std::vector cached_scan_results; + std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name); + if (status == WIFI_SUCCESS) { + on_results_user_callback(id, cached_scan_results); + return; + } + FALLTHROUGH_INTENDED; + } + // Fall through if failed. Failure to retrieve cached scan + // results should trigger a background scan failure. + case WIFI_SCAN_FAILED: + on_failure_user_callback(id); + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + return; + } + LOG(FATAL) << "Unexpected gscan event received: " << event; + }; + + on_gscan_full_result_internal_callback = [on_full_result_user_callback]( + wifi_request_id id, wifi_scan_result* result, + uint32_t buckets_scanned) { + if (result) { + on_full_result_user_callback(id, result, buckets_scanned); + } + }; + + wifi_scan_result_handler handler = {onAsyncGscanFullResult, onAsyncGscanEvent}; + wifi_error status = + global_func_table_.wifi_start_gscan(id, getIfaceHandle(iface_name), params, handler); + if (status != WIFI_SUCCESS) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, wifi_request_id id) { + // If there is no an ongoing background scan, reject stop requests. + // TODO(b/32337212): This needs to be handled by the HIDL object because we + // need to return the NOT_STARTED error code. + if (!on_gscan_event_internal_callback && !on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name)); + // If the request Id is wrong, don't stop the ongoing background scan. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +std::pair> WifiLegacyHal::getValidFrequenciesForBand( + const std::string& iface_name, wifi_band band) { + static_assert(sizeof(uint32_t) >= sizeof(wifi_channel), + "Wifi Channel cannot be represented in output"); + std::vector freqs; + freqs.resize(kMaxGscanFrequenciesForBand); + int32_t num_freqs = 0; + wifi_error status = global_func_table_.wifi_get_valid_channels( + getIfaceHandle(iface_name), band, freqs.size(), + reinterpret_cast(freqs.data()), &num_freqs); + CHECK(num_freqs >= 0 && static_cast(num_freqs) <= kMaxGscanFrequenciesForBand); + freqs.resize(num_freqs); + return {status, std::move(freqs)}; +} + +wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) { + return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1); +} + +wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, bool debug) { + wifi_link_layer_params params; + params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold; + params.aggressive_statistics_gathering = debug; + return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), params); +} + +wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) { + // TODO: Do we care about these responses? + uint32_t clear_mask_rsp; + uint8_t stop_rsp; + return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF, + &clear_mask_rsp, 1, &stop_rsp); +} + +std::pair WifiLegacyHal::getLinkLayerStats( + const std::string& iface_name) { + LinkLayerStats link_stats{}; + LinkLayerStats* link_stats_ptr = &link_stats; + + on_link_layer_stats_result_internal_callback = [&link_stats_ptr]( + wifi_request_id /* id */, + wifi_iface_stat* iface_stats_ptr, + int num_radios, + wifi_radio_stat* radio_stats_ptr) { + wifi_radio_stat* l_radio_stats_ptr; + wifi_peer_info* l_peer_info_stats_ptr; + + if (iface_stats_ptr != nullptr) { + link_stats_ptr->iface = *iface_stats_ptr; + l_peer_info_stats_ptr = iface_stats_ptr->peer_info; + for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) { + WifiPeerInfo peer; + peer.peer_info = *l_peer_info_stats_ptr; + if (l_peer_info_stats_ptr->num_rate > 0) { + /* Copy the rate stats */ + peer.rate_stats.assign( + l_peer_info_stats_ptr->rate_stats, + l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate); + } + peer.peer_info.num_rate = 0; + link_stats_ptr->peers.push_back(peer); + l_peer_info_stats_ptr = + (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) + + (sizeof(wifi_rate_stat) * + l_peer_info_stats_ptr->num_rate)); + } + link_stats_ptr->iface.num_peers = 0; + } else { + LOG(ERROR) << "Invalid iface stats in link layer stats"; + } + if (num_radios <= 0 || radio_stats_ptr == nullptr) { + LOG(ERROR) << "Invalid radio stats in link layer stats"; + return; + } + l_radio_stats_ptr = radio_stats_ptr; + for (int i = 0; i < num_radios; i++) { + LinkLayerRadioStats radio; + + radio.stats = *l_radio_stats_ptr; + // Copy over the tx level array to the separate vector. + if (l_radio_stats_ptr->num_tx_levels > 0 && + l_radio_stats_ptr->tx_time_per_levels != nullptr) { + radio.tx_time_per_levels.assign( + l_radio_stats_ptr->tx_time_per_levels, + l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels); + } + radio.stats.num_tx_levels = 0; + radio.stats.tx_time_per_levels = nullptr; + /* Copy over the channel stat to separate vector */ + if (l_radio_stats_ptr->num_channels > 0) { + /* Copy the channel stats */ + radio.channel_stats.assign( + l_radio_stats_ptr->channels, + l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels); + } + link_stats_ptr->radios.push_back(radio); + l_radio_stats_ptr = + (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) + + (sizeof(wifi_channel_stat) * + l_radio_stats_ptr->num_channels)); + } + }; + + wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name), + {onSyncLinkLayerStatsResult}); + on_link_layer_stats_result_internal_callback = nullptr; + return {status, link_stats}; +} + +wifi_error WifiLegacyHal::startRssiMonitoring( + const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi, + const on_rssi_threshold_breached_callback& on_threshold_breached_user_callback) { + if (on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_rssi_threshold_breached_internal_callback = [on_threshold_breached_user_callback]( + wifi_request_id id, uint8_t* bssid_ptr, + int8_t rssi) { + if (!bssid_ptr) { + return; + } + std::array bssid_arr; + // |bssid_ptr| pointer is assumed to have 6 bytes for the mac + // address. + std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr)); + on_threshold_breached_user_callback(id, bssid_arr, rssi); + }; + wifi_error status = global_func_table_.wifi_start_rssi_monitoring( + id, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached}); + if (status != WIFI_SUCCESS) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, wifi_request_id id) { + if (!on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = + global_func_table_.wifi_stop_rssi_monitoring(id, getIfaceHandle(iface_name)); + // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +std::pair WifiLegacyHal::getRoamingCapabilities( + const std::string& iface_name) { + wifi_roaming_capabilities caps; + wifi_error status = + global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name, + const wifi_roaming_config& config) { + wifi_roaming_config config_internal = config; + return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal); +} + +wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name, + fw_roaming_state_t state) { + return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state); +} + +wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) { + return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable); +} + +wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name, + uint32_t cmd_id, uint16_t ether_type, + const std::vector& ip_packet_data, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms) { + std::vector ip_packet_data_internal(ip_packet_data); + std::vector src_address_internal(src_address.data(), + src_address.data() + src_address.size()); + std::vector dst_address_internal(dst_address.data(), + dst_address.data() + dst_address.size()); + return global_func_table_.wifi_start_sending_offloaded_packet( + cmd_id, getIfaceHandle(iface_name), ether_type, ip_packet_data_internal.data(), + ip_packet_data_internal.size(), src_address_internal.data(), + dst_address_internal.data(), period_in_ms); +} + +wifi_error WifiLegacyHal::stopSendingOffloadedPacket(const std::string& iface_name, + uint32_t cmd_id) { + return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id, + getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario) { + return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario); +} + +wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) { + return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) { + return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode); +} + +wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode, + uint32_t completion_window) { + return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode, + completion_window); +} + +wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end, + uint32_t access_category) { + return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end, + access_category); +} + +wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() { + return global_func_table_.wifi_reset_dscp_mapping(global_handle_); +} + +std::pair WifiLegacyHal::getLoggerSupportedFeatureSet( + const std::string& iface_name) { + uint32_t supported_feature_flags = 0; + wifi_error status = WIFI_SUCCESS; + + wifi_interface_handle iface_handle = getIfaceHandle(iface_name); + + if (iface_handle) { + status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle, + &supported_feature_flags); + } + return {status, supported_feature_flags}; +} + +wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) { + return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name)); +} + +std::pair> WifiLegacyHal::getTxPktFates( + const std::string& iface_name) { + std::vector tx_pkt_fates; + tx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = global_func_table_.wifi_get_tx_pkt_fates( + getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + tx_pkt_fates.resize(num_fates); + return {status, std::move(tx_pkt_fates)}; +} + +std::pair> WifiLegacyHal::getRxPktFates( + const std::string& iface_name) { + std::vector rx_pkt_fates; + rx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = global_func_table_.wifi_get_rx_pkt_fates( + getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + rx_pkt_fates.resize(num_fates); + return {status, std::move(rx_pkt_fates)}; +} + +std::pair WifiLegacyHal::getWakeReasonStats( + const std::string& iface_name) { + WakeReasonStats stats; + stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + + // This legacy struct needs separate memory to store the variable sized wake + // reason types. + stats.wake_reason_cnt.cmd_event_wake_cnt = + reinterpret_cast(stats.cmd_event_wake_cnt.data()); + stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size(); + stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0; + stats.wake_reason_cnt.driver_fw_local_wake_cnt = + reinterpret_cast(stats.driver_fw_local_wake_cnt.data()); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = stats.driver_fw_local_wake_cnt.size(); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0; + + wifi_error status = global_func_table_.wifi_get_wake_reason_stats(getIfaceHandle(iface_name), + &stats.wake_reason_cnt); + + CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 && + static_cast(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.cmd_event_wake_cnt.resize(stats.wake_reason_cnt.cmd_event_wake_cnt_used); + stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr; + + CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 && + static_cast(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used); + stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr; + + return {status, stats}; +} + +wifi_error WifiLegacyHal::registerRingBufferCallbackHandler( + const std::string& iface_name, const on_ring_buffer_data_callback& on_user_data_callback) { + if (on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = [on_user_data_callback]( + char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status) { + if (status && buffer) { + std::vector buffer_vector(reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size); + on_user_data_callback(ring_name, buffer_vector, *status); + } + }; + wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name), + {onAsyncRingBufferData}); + if (status != WIFI_SUCCESS) { + on_ring_buffer_data_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) { + if (!on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = nullptr; + return global_func_table_.wifi_reset_log_handler(0, getIfaceHandle(iface_name)); +} + +std::pair> WifiLegacyHal::getRingBuffersStatus( + const std::string& iface_name) { + std::vector ring_buffers_status; + ring_buffers_status.resize(kMaxRingBuffers); + uint32_t num_rings = kMaxRingBuffers; + wifi_error status = global_func_table_.wifi_get_ring_buffers_status( + getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data()); + CHECK(num_rings <= kMaxRingBuffers); + ring_buffers_status.resize(num_rings); + return {status, std::move(ring_buffers_status)}; +} + +wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name, + const std::string& ring_name, + uint32_t verbose_level, uint32_t max_interval_sec, + uint32_t min_data_size) { + return global_func_table_.wifi_start_logging(getIfaceHandle(iface_name), verbose_level, 0, + max_interval_sec, min_data_size, + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name, + const std::string& ring_name) { + return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name), + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler( + const std::string& iface_name, const on_error_alert_callback& on_user_alert_callback) { + if (on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = [on_user_alert_callback](wifi_request_id id, char* buffer, + int buffer_size, int err_code) { + if (buffer) { + CHECK(id == 0); + on_user_alert_callback( + err_code, + std::vector(reinterpret_cast(buffer), + reinterpret_cast(buffer) + buffer_size)); + } + }; + wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name), + {onAsyncErrorAlert}); + if (status != WIFI_SUCCESS) { + on_error_alert_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) { + if (!on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = nullptr; + return global_func_table_.wifi_reset_alert_handler(0, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback) { + if (on_radio_mode_change_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_radio_mode_change_internal_callback = [on_user_change_callback]( + wifi_request_id /* id */, uint32_t num_macs, + wifi_mac_info* mac_infos_arr) { + if (num_macs > 0 && mac_infos_arr) { + std::vector mac_infos_vec; + for (uint32_t i = 0; i < num_macs; i++) { + WifiMacInfo mac_info; + mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id; + mac_info.mac_band = mac_infos_arr[i].mac_band; + for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) { + WifiIfaceInfo iface_info; + iface_info.name = mac_infos_arr[i].iface_info[j].iface_name; + iface_info.channel = mac_infos_arr[i].iface_info[j].channel; + mac_info.iface_infos.push_back(iface_info); + } + mac_infos_vec.push_back(mac_info); + } + on_user_change_callback(mac_infos_vec); + } + }; + wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler( + 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange}); + if (status != WIFI_SUCCESS) { + on_radio_mode_change_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback) { + if (on_subsystem_restart_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) { + on_restart_callback(error); + }; + wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler( + global_handle_, {onAsyncSubsystemRestart}); + if (status != WIFI_SUCCESS) { + on_subsystem_restart_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::startRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector& rtt_configs, + const on_rtt_results_callback& on_results_user_callback) { + if (on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_rtt_results_internal_callback = [on_results_user_callback](wifi_request_id id, + unsigned num_results, + wifi_rtt_result* rtt_results[]) { + if (num_results > 0 && !rtt_results) { + LOG(ERROR) << "Unexpected nullptr in RTT results"; + return; + } + std::vector rtt_results_vec; + std::copy_if(rtt_results, rtt_results + num_results, back_inserter(rtt_results_vec), + [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; }); + on_results_user_callback(id, rtt_results_vec); + }; + + std::vector rtt_configs_internal(rtt_configs); + wifi_error status = global_func_table_.wifi_rtt_range_request( + id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(), + {onAsyncRttResults}); + if (status != WIFI_SUCCESS) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::cancelRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector>& mac_addrs) { + if (!on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + static_assert(sizeof(mac_addr) == sizeof(std::array), "MAC address size mismatch"); + // TODO: How do we handle partial cancels (i.e only a subset of enabled mac + // addressed are cancelled). + std::vector> mac_addrs_internal(mac_addrs); + wifi_error status = global_func_table_.wifi_rtt_range_cancel( + id, getIfaceHandle(iface_name), mac_addrs.size(), + reinterpret_cast(mac_addrs_internal.data())); + // If the request Id is wrong, don't stop the ongoing range request. Any + // other error should be treated as the end of rtt ranging. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +std::pair WifiLegacyHal::getRttCapabilities( + const std::string& iface_name) { + wifi_rtt_capabilities rtt_caps; + wifi_error status = + global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps); + return {status, rtt_caps}; +} + +std::pair WifiLegacyHal::getRttResponderInfo( + const std::string& iface_name) { + wifi_rtt_responder rtt_responder; + wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name), + &rtt_responder); + return {status, rtt_responder}; +} + +wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, wifi_request_id id, + const wifi_channel_info& channel_hint, + uint32_t max_duration_secs, + const wifi_rtt_responder& info) { + wifi_rtt_responder info_internal(info); + return global_func_table_.wifi_enable_responder(id, getIfaceHandle(iface_name), channel_hint, + max_duration_secs, &info_internal); +} + +wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) { + return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id, + const wifi_lci_information& info) { + wifi_lci_information info_internal(info); + return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal); +} + +wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id, + const wifi_lcr_information& info) { + wifi_lcr_information info_internal(info); + return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal); +} + +wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name, + const NanCallbackHandlers& user_callbacks) { + on_nan_notify_response_user_callback = user_callbacks.on_notify_response; + on_nan_event_publish_terminated_user_callback = user_callbacks.on_event_publish_terminated; + on_nan_event_match_user_callback = user_callbacks.on_event_match; + on_nan_event_match_expired_user_callback = user_callbacks.on_event_match_expired; + on_nan_event_subscribe_terminated_user_callback = user_callbacks.on_event_subscribe_terminated; + on_nan_event_followup_user_callback = user_callbacks.on_event_followup; + on_nan_event_disc_eng_event_user_callback = user_callbacks.on_event_disc_eng_event; + on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled; + on_nan_event_tca_user_callback = user_callbacks.on_event_tca; + on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload; + on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request; + on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm; + on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end; + on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up; + on_nan_event_range_request_user_callback = user_callbacks.on_event_range_request; + on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report; + on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update; + + return global_func_table_.wifi_nan_register_handler( + getIfaceHandle(iface_name), + {onAysncNanNotifyResponse, onAysncNanEventPublishReplied, + onAysncNanEventPublishTerminated, onAysncNanEventMatch, onAysncNanEventMatchExpired, + onAysncNanEventSubscribeTerminated, onAysncNanEventFollowup, + onAysncNanEventDiscEngEvent, onAysncNanEventDisabled, onAysncNanEventTca, + onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest, + onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd, + onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest, + onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate}); +} + +wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id, + const NanEnableRequest& msg) { + NanEnableRequest msg_internal(msg); + return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) { + return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id, + const NanPublishRequest& msg) { + NanPublishRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id, + const NanPublishCancelRequest& msg) { + NanPublishCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeRequest& msg) { + NanSubscribeRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name, + transaction_id id, + const NanSubscribeCancelRequest& msg) { + NanSubscribeCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name, + transaction_id id, + const NanTransmitFollowupRequest& msg) { + NanTransmitFollowupRequest msg_internal(msg); + return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id, + const NanStatsRequest& msg) { + NanStatsRequest msg_internal(msg); + return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id, + const NanConfigRequest& msg) { + NanConfigRequest msg_internal(msg); + return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id, + const NanTCARequest& msg) { + NanTCARequest msg_internal(msg); + return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name, + transaction_id id, + const NanBeaconSdfPayloadRequest& msg) { + NanBeaconSdfPayloadRequest msg_internal(msg); + return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name), + &msg_internal); +} + +std::pair WifiLegacyHal::nanGetVersion() { + NanVersion version; + wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version); + return {status, version}; +} + +wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) { + return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name), + makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name), + makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id, + const NanDataPathInitiatorRequest& msg) { + NanDataPathInitiatorRequest msg_internal(msg); + return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name), + &msg_internal); +} + +wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name, + transaction_id id, + const NanDataPathIndicationResponse& msg) { + NanDataPathIndicationResponse msg_internal(msg); + return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name), + &msg_internal); +} + +typedef struct { + u8 num_ndp_instances; + NanDataPathId ndp_instance_id; +} NanDataPathEndSingleNdpIdRequest; + +wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, transaction_id id, + uint32_t ndpInstanceId) { + NanDataPathEndSingleNdpIdRequest msg; + msg.num_ndp_instances = 1; + msg.ndp_instance_id = ndpInstanceId; + wifi_error status = global_func_table_.wifi_nan_data_end(id, getIfaceHandle(iface_name), + (NanDataPathEndRequest*)&msg); + return status; +} + +wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name, + std::array code) { + std::string code_str(code.data(), code.data() + code.size()); + return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str()); +} + +wifi_error WifiLegacyHal::retrieveIfaceHandles() { + wifi_interface_handle* iface_handles = nullptr; + int num_iface_handles = 0; + wifi_error status = + global_func_table_.wifi_get_ifaces(global_handle_, &num_iface_handles, &iface_handles); + if (status != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to enumerate interface handles"; + return status; + } + iface_name_to_handle_.clear(); + for (int i = 0; i < num_iface_handles; ++i) { + std::array iface_name_arr = {}; + status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(), + iface_name_arr.size()); + if (status != WIFI_SUCCESS) { + LOG(WARNING) << "Failed to get interface handle name"; + continue; + } + // Assuming the interface name is null terminated since the legacy HAL + // API does not return a size. + std::string iface_name(iface_name_arr.data()); + LOG(INFO) << "Adding interface handle for " << iface_name; + iface_name_to_handle_[iface_name] = iface_handles[i]; + } + return WIFI_SUCCESS; +} + +wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) { + const auto iface_handle_iter = iface_name_to_handle_.find(iface_name); + if (iface_handle_iter == iface_name_to_handle_.end()) { + LOG(ERROR) << "Unknown iface name: " << iface_name; + return nullptr; + } + return iface_handle_iter->second; +} + +void WifiLegacyHal::runEventLoop() { + LOG(DEBUG) << "Starting legacy HAL event loop"; + global_func_table_.wifi_event_loop(global_handle_); + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (!awaiting_event_loop_termination_) { + LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping"; + } + LOG(DEBUG) << "Legacy HAL event loop terminated"; + awaiting_event_loop_termination_ = false; + stop_wait_cv_.notify_one(); +} + +std::pair> WifiLegacyHal::getGscanCachedResults( + const std::string& iface_name) { + std::vector cached_scan_results; + cached_scan_results.resize(kMaxCachedGscanResults); + int32_t num_results = 0; + wifi_error status = global_func_table_.wifi_get_cached_gscan_results( + getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(), + cached_scan_results.data(), &num_results); + CHECK(num_results >= 0 && static_cast(num_results) <= kMaxCachedGscanResults); + cached_scan_results.resize(num_results); + // Check for invalid IE lengths in these cached scan results and correct it. + for (auto& cached_scan_result : cached_scan_results) { + int num_scan_results = cached_scan_result.num_results; + for (int i = 0; i < num_scan_results; i++) { + auto& scan_result = cached_scan_result.results[i]; + if (scan_result.ie_length > 0) { + LOG(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length; + scan_result.ie_length = 0; + } + } + } + return {status, std::move(cached_scan_results)}; +} + +wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype) { + // Create the interface if it doesn't exist. If interface already exist, + // Vendor Hal should return WIFI_SUCCESS. + wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_, + ifname.c_str(), iftype); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) { + // Delete the interface if it was created dynamically. + wifi_error status = + global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str()); + return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status); +} + +wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname, + wifi_error status) { + if (status == WIFI_SUCCESS) { + // refresh list of handlers now. + status = retrieveIfaceHandles(); + } else if (status == WIFI_ERROR_NOT_SUPPORTED) { + // Vendor hal does not implement this API. Such vendor implementations + // are expected to create / delete interface by other means. + + // check if interface exists. + if (if_nametoindex(ifname.c_str())) { + status = retrieveIfaceHandles(); + } + } + return status; +} + +wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) { + std::array buffer; + + wifi_error res = global_func_table_.wifi_get_supported_iface_name( + global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size()); + if (res == WIFI_SUCCESS) ifname = buffer.data(); + + return res; +} + +wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) { + return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_, + getIfaceHandle(ifname)); +} + +wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) { + return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case); +} + +wifi_error WifiLegacyHal::setCoexUnsafeChannels( + std::vector unsafe_channels, uint32_t restrictions) { + return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(), + unsafe_channels.data(), restrictions); +} + +wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) { + return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode); +} + +wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name, + const TwtCallbackHandlers& user_callbacks) { + on_twt_event_setup_response_callback = user_callbacks.on_setup_response; + on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion; + on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received; + on_twt_event_device_notify_callback = user_callbacks.on_device_notify; + + return global_func_table_.wifi_twt_register_handler( + getIfaceHandle(iface_name), + {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion, + onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify}); +} + +std::pair WifiLegacyHal::twtGetCapability( + const std::string& iface_name) { + TwtCapabilitySet capSet; + wifi_error status = + global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet); + return {status, capSet}; +} + +wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name, + const TwtSetupRequest& msg) { + TwtSetupRequest msgInternal(msg); + return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal); +} + +wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name, + const TwtTeardownRequest& msg) { + TwtTeardownRequest msgInternal(msg); + return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal); +} + +wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name, + const TwtInfoFrameRequest& msg) { + TwtInfoFrameRequest msgInternal(msg); + return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal); +} + +std::pair WifiLegacyHal::twtGetStats(const std::string& iface_name, + uint8_t configId) { + TwtStats stats; + wifi_error status = + global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats); + return {status, stats}; +} + +wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) { + return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId); +} + +wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) { + return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier); +} + +std::pair> WifiLegacyHal::getUsableChannels( + uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) { + std::vector channels; + channels.resize(kMaxWifiUsableChannels); + uint32_t size = 0; + wifi_error status = global_func_table_.wifi_get_usable_channels( + global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size, + reinterpret_cast(channels.data())); + CHECK(size >= 0 && size <= kMaxWifiUsableChannels); + channels.resize(size); + return {status, std::move(channels)}; +} + +wifi_error WifiLegacyHal::triggerSubsystemRestart() { + return global_func_table_.wifi_trigger_subsystem_restart(global_handle_); +} + +wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) { + return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor); +} + +std::pair +WifiLegacyHal::getSupportedRadioCombinationsMatrix() { + char* buffer = new char[kMaxSupportedRadioCombinationsMatrixLength]; + std::fill(buffer, buffer + kMaxSupportedRadioCombinationsMatrixLength, 0); + uint32_t size = 0; + wifi_radio_combination_matrix* radio_combination_matrix_ptr = + reinterpret_cast(buffer); + wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix( + global_handle_, kMaxSupportedRadioCombinationsMatrixLength, &size, + radio_combination_matrix_ptr); + CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength); + return {status, radio_combination_matrix_ptr}; +} + +wifi_error WifiLegacyHal::chreNanRttRequest(const std::string& iface_name, bool enable) { + if (enable) + return global_func_table_.wifi_nan_rtt_chre_enable_request(0, getIfaceHandle(iface_name), + NULL); + else + return global_func_table_.wifi_nan_rtt_chre_disable_request(0, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::chreRegisterHandler(const std::string& iface_name, + const ChreCallbackHandlers& handler) { + if (on_chre_nan_rtt_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_chre_nan_rtt_internal_callback = handler.on_wifi_chre_nan_rtt_state; + + wifi_error status = global_func_table_.wifi_chre_register_handler(getIfaceHandle(iface_name), + {onAsyncChreNanRttState}); + if (status != WIFI_SUCCESS) { + on_chre_nan_rtt_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::enableWifiTxPowerLimits(const std::string& iface_name, bool enable) { + return global_func_table_.wifi_enable_tx_power_limits(getIfaceHandle(iface_name), enable); +} + +wifi_error WifiLegacyHal::getWifiCachedScanResults( + const std::string& iface_name, const CachedScanResultsCallbackHandlers& handler) { + on_cached_scan_results_internal_callback = handler.on_cached_scan_results; + + wifi_error status = global_func_table_.wifi_get_cached_scan_results(getIfaceHandle(iface_name), + {onSyncCachedScanResults}); + + on_cached_scan_results_internal_callback = nullptr; + return status; +} + +void WifiLegacyHal::invalidate() { + global_handle_ = nullptr; + iface_name_to_handle_.clear(); + on_driver_memory_dump_internal_callback = nullptr; + on_firmware_memory_dump_internal_callback = nullptr; + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + on_link_layer_stats_result_internal_callback = nullptr; + on_rssi_threshold_breached_internal_callback = nullptr; + on_ring_buffer_data_internal_callback = nullptr; + on_error_alert_internal_callback = nullptr; + on_radio_mode_change_internal_callback = nullptr; + on_subsystem_restart_internal_callback = nullptr; + on_rtt_results_internal_callback = nullptr; + on_nan_notify_response_user_callback = nullptr; + on_nan_event_publish_terminated_user_callback = nullptr; + on_nan_event_match_user_callback = nullptr; + on_nan_event_match_expired_user_callback = nullptr; + on_nan_event_subscribe_terminated_user_callback = nullptr; + on_nan_event_followup_user_callback = nullptr; + on_nan_event_disc_eng_event_user_callback = nullptr; + on_nan_event_disabled_user_callback = nullptr; + on_nan_event_tca_user_callback = nullptr; + on_nan_event_beacon_sdf_payload_user_callback = nullptr; + on_nan_event_data_path_request_user_callback = nullptr; + on_nan_event_data_path_confirm_user_callback = nullptr; + on_nan_event_data_path_end_user_callback = nullptr; + on_nan_event_transmit_follow_up_user_callback = nullptr; + on_nan_event_range_request_user_callback = nullptr; + on_nan_event_range_report_user_callback = nullptr; + on_nan_event_schedule_update_user_callback = nullptr; + on_twt_event_setup_response_callback = nullptr; + on_twt_event_teardown_completion_callback = nullptr; + on_twt_event_info_frame_received_callback = nullptr; + on_twt_event_device_notify_callback = nullptr; + on_chre_nan_rtt_internal_callback = nullptr; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h new file mode 100644 index 0000000..b6bd5ea --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal.h @@ -0,0 +1,739 @@ +/* + * 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 WIFI_LEGACY_HAL_H_ +#define WIFI_LEGACY_HAL_H_ + +#include +#include +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +// This is in a separate namespace to prevent typename conflicts between +// the legacy HAL types and the HIDL interface types. +namespace legacy_hal { +// Import all the types defined inside the legacy HAL header files into this +// namespace. +using ::chre_nan_rtt_state; +using ::frame_info; +using ::frame_type; +using ::FRAME_TYPE_80211_MGMT; +using ::FRAME_TYPE_ETHERNET_II; +using ::FRAME_TYPE_UNKNOWN; +using ::fw_roaming_state_t; +using ::mac_addr; +using ::NAN_CHANNEL_24G_BAND; +using ::NAN_CHANNEL_5G_BAND_HIGH; +using ::NAN_CHANNEL_5G_BAND_LOW; +using ::NAN_DISABLE_RANGE_REPORT; +using ::NAN_DO_NOT_USE_SRF; +using ::NAN_DP_CHANNEL_NOT_REQUESTED; +using ::NAN_DP_CONFIG_NO_SECURITY; +using ::NAN_DP_CONFIG_SECURITY; +using ::NAN_DP_END; +using ::NAN_DP_FORCE_CHANNEL_SETUP; +using ::NAN_DP_INITIATOR_RESPONSE; +using ::NAN_DP_INTERFACE_CREATE; +using ::NAN_DP_INTERFACE_DELETE; +using ::NAN_DP_REQUEST_ACCEPT; +using ::NAN_DP_REQUEST_CHANNEL_SETUP; +using ::NAN_DP_REQUEST_REJECT; +using ::NAN_DP_RESPONDER_RESPONSE; +using ::NAN_GET_CAPABILITIES; +using ::NAN_MATCH_ALG_MATCH_CONTINUOUS; +using ::NAN_MATCH_ALG_MATCH_NEVER; +using ::NAN_MATCH_ALG_MATCH_ONCE; +using ::NAN_PUBLISH_TYPE_SOLICITED; +using ::NAN_PUBLISH_TYPE_UNSOLICITED; +using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED; +using ::NAN_RANGING_AUTO_RESPONSE_DISABLE; +using ::NAN_RANGING_AUTO_RESPONSE_ENABLE; +using ::NAN_RANGING_DISABLE; +using ::NAN_RANGING_ENABLE; +using ::NAN_RESPONSE_BEACON_SDF_PAYLOAD; +using ::NAN_RESPONSE_CONFIG; +using ::NAN_RESPONSE_DISABLED; +using ::NAN_RESPONSE_ENABLED; +using ::NAN_RESPONSE_ERROR; +using ::NAN_RESPONSE_PUBLISH; +using ::NAN_RESPONSE_PUBLISH_CANCEL; +using ::NAN_RESPONSE_STATS; +using ::NAN_RESPONSE_SUBSCRIBE; +using ::NAN_RESPONSE_SUBSCRIBE_CANCEL; +using ::NAN_RESPONSE_TCA; +using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP; +using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE; +using ::NAN_SECURITY_KEY_INPUT_PMK; +using ::NAN_SERVICE_ACCEPT_POLICY_ALL; +using ::NAN_SERVICE_ACCEPT_POLICY_NONE; +using ::NAN_SRF_ATTR_BLOOM_FILTER; +using ::NAN_SRF_ATTR_PARTIAL_MAC_ADDR; +using ::NAN_SRF_INCLUDE_DO_NOT_RESPOND; +using ::NAN_SRF_INCLUDE_RESPOND; +using ::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; +using ::NAN_SSI_REQUIRED_IN_MATCH_IND; +using ::NAN_STATUS_ALREADY_ENABLED; +using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL; +using ::NAN_STATUS_INTERNAL_FAILURE; +using ::NAN_STATUS_INVALID_NDP_ID; +using ::NAN_STATUS_INVALID_PARAM; +using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; +using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID; +using ::NAN_STATUS_NAN_NOT_ALLOWED; +using ::NAN_STATUS_NO_OTA_ACK; +using ::NAN_STATUS_NO_RESOURCE_AVAILABLE; +using ::NAN_STATUS_PROTOCOL_FAILURE; +using ::NAN_STATUS_SUCCESS; +using ::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED; +using ::NAN_SUBSCRIBE_TYPE_ACTIVE; +using ::NAN_SUBSCRIBE_TYPE_PASSIVE; +using ::NAN_TRANSMIT_IN_DW; +using ::NAN_TRANSMIT_IN_FAW; +using ::NAN_TX_PRIORITY_HIGH; +using ::NAN_TX_PRIORITY_NORMAL; +using ::NAN_TX_TYPE_BROADCAST; +using ::NAN_TX_TYPE_UNICAST; +using ::NAN_USE_SRF; +using ::NanBeaconSdfPayloadInd; +using ::NanCapabilities; +using ::NanChannelInfo; +using ::NanConfigRequest; +using ::NanDataPathChannelCfg; +using ::NanDataPathConfirmInd; +using ::NanDataPathEndInd; +using ::NanDataPathIndicationResponse; +using ::NanDataPathInitiatorRequest; +using ::NanDataPathRequestInd; +using ::NanDataPathScheduleUpdateInd; +using ::NanDisabledInd; +using ::NanDiscEngEventInd; +using ::NanEnableRequest; +using ::NanFollowupInd; +using ::NanMatchAlg; +using ::NanMatchExpiredInd; +using ::NanMatchInd; +using ::NanPublishCancelRequest; +using ::NanPublishRequest; +using ::NanPublishTerminatedInd; +using ::NanPublishType; +using ::NanRangeReportInd; +using ::NanRangeRequestInd; +using ::NanResponseMsg; +using ::NanSRFType; +using ::NanStatusType; +using ::NanSubscribeCancelRequest; +using ::NanSubscribeRequest; +using ::NanSubscribeTerminatedInd; +using ::NanSubscribeType; +using ::NanTransmitFollowupInd; +using ::NanTransmitFollowupRequest; +using ::NanTxType; +using ::ROAMING_DISABLE; +using ::ROAMING_ENABLE; +using ::RTT_PEER_AP; +using ::RTT_PEER_NAN; +using ::RTT_PEER_P2P_CLIENT; +using ::RTT_PEER_P2P_GO; +using ::RTT_PEER_STA; +using ::rtt_peer_type; +using ::RTT_STATUS_ABORTED; +using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; +using ::RTT_STATUS_FAIL_BUSY_TRY_LATER; +using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; +using ::RTT_STATUS_FAIL_INVALID_TS; +using ::RTT_STATUS_FAIL_NO_CAPABILITY; +using ::RTT_STATUS_FAIL_NO_RSP; +using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET; +using ::RTT_STATUS_FAIL_PROTOCOL; +using ::RTT_STATUS_FAIL_REJECTED; +using ::RTT_STATUS_FAIL_SCHEDULE; +using ::RTT_STATUS_FAIL_TM_TIMEOUT; +using ::RTT_STATUS_FAILURE; +using ::RTT_STATUS_INVALID_REQ; +using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED; +using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE; +using ::RTT_STATUS_NO_WIFI; +using ::RTT_STATUS_SUCCESS; +using ::RTT_TYPE_1_SIDED; +using ::RTT_TYPE_2_SIDED; +using ::RX_PKT_FATE_DRV_DROP_FILTER; +using ::RX_PKT_FATE_DRV_DROP_INVALID; +using ::RX_PKT_FATE_DRV_DROP_NOBUFS; +using ::RX_PKT_FATE_DRV_DROP_OTHER; +using ::RX_PKT_FATE_DRV_QUEUED; +using ::RX_PKT_FATE_FW_DROP_FILTER; +using ::RX_PKT_FATE_FW_DROP_INVALID; +using ::RX_PKT_FATE_FW_DROP_NOBUFS; +using ::RX_PKT_FATE_FW_DROP_OTHER; +using ::RX_PKT_FATE_FW_QUEUED; +using ::RX_PKT_FATE_SUCCESS; +using ::ssid_t; +using ::transaction_id; +using ::TX_PKT_FATE_ACKED; +using ::TX_PKT_FATE_DRV_DROP_INVALID; +using ::TX_PKT_FATE_DRV_DROP_NOBUFS; +using ::TX_PKT_FATE_DRV_DROP_OTHER; +using ::TX_PKT_FATE_DRV_QUEUED; +using ::TX_PKT_FATE_FW_DROP_INVALID; +using ::TX_PKT_FATE_FW_DROP_NOBUFS; +using ::TX_PKT_FATE_FW_DROP_OTHER; +using ::TX_PKT_FATE_FW_QUEUED; +using ::TX_PKT_FATE_SENT; +using ::WIFI_AC_BE; +using ::WIFI_AC_BK; +using ::WIFI_AC_VI; +using ::WIFI_AC_VO; +using ::WIFI_ANTENNA_1X1; +using ::WIFI_ANTENNA_2X2; +using ::WIFI_ANTENNA_3X3; +using ::WIFI_ANTENNA_4X4; +using ::WIFI_ANTENNA_UNSPECIFIED; +using ::wifi_band; +using ::WIFI_BAND_A; +using ::WIFI_BAND_A_DFS; +using ::WIFI_BAND_A_WITH_DFS; +using ::WIFI_BAND_ABG; +using ::WIFI_BAND_ABG_WITH_DFS; +using ::WIFI_BAND_BG; +using ::WIFI_BAND_UNSPECIFIED; +using ::wifi_cached_scan_report; +using ::wifi_cached_scan_results; +using ::WIFI_CHAN_WIDTH_10; +using ::WIFI_CHAN_WIDTH_160; +using ::WIFI_CHAN_WIDTH_20; +using ::WIFI_CHAN_WIDTH_320; +using ::WIFI_CHAN_WIDTH_40; +using ::WIFI_CHAN_WIDTH_5; +using ::WIFI_CHAN_WIDTH_80; +using ::WIFI_CHAN_WIDTH_80P80; +using ::WIFI_CHAN_WIDTH_INVALID; +using ::wifi_channel_info; +using ::wifi_channel_stat; +using ::wifi_channel_width; +using ::wifi_coex_restriction; +using ::wifi_coex_unsafe_channel; +using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED; +using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY; +using ::wifi_error; +using ::WIFI_ERROR_BUSY; +using ::WIFI_ERROR_INVALID_ARGS; +using ::WIFI_ERROR_INVALID_REQUEST_ID; +using ::WIFI_ERROR_NONE; +using ::WIFI_ERROR_NOT_AVAILABLE; +using ::WIFI_ERROR_NOT_SUPPORTED; +using ::WIFI_ERROR_OUT_OF_MEMORY; +using ::WIFI_ERROR_TIMED_OUT; +using ::WIFI_ERROR_TOO_MANY_REQUESTS; +using ::WIFI_ERROR_UNINITIALIZED; +using ::WIFI_ERROR_UNKNOWN; +using ::wifi_gscan_capabilities; +using ::wifi_hal_fn; +using ::wifi_information_element; +using ::WIFI_INTERFACE_IBSS; +using ::WIFI_INTERFACE_MESH; +using ::wifi_interface_mode; +using ::WIFI_INTERFACE_NAN; +using ::WIFI_INTERFACE_P2P_CLIENT; +using ::WIFI_INTERFACE_P2P_GO; +using ::WIFI_INTERFACE_SOFTAP; +using ::WIFI_INTERFACE_STA; +using ::WIFI_INTERFACE_TDLS; +using ::wifi_interface_type; +using ::WIFI_INTERFACE_TYPE_AP; +using ::WIFI_INTERFACE_TYPE_NAN; +using ::WIFI_INTERFACE_TYPE_P2P; +using ::WIFI_INTERFACE_TYPE_STA; +using ::WIFI_INTERFACE_UNKNOWN; +using ::wifi_latency_mode; +using ::WIFI_LATENCY_MODE_LOW; +using ::WIFI_LATENCY_MODE_NORMAL; +using ::wifi_lci_information; +using ::wifi_lcr_information; +using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED; +using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED; +using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED; +using ::WIFI_LOGGER_PACKET_FATE_SUPPORTED; +using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED; +using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED; +using ::WIFI_MOTION_EXPECTED; +using ::WIFI_MOTION_NOT_EXPECTED; +using ::wifi_motion_pattern; +using ::WIFI_MOTION_UNKNOWN; +using ::wifi_multi_sta_use_case; +using ::wifi_power_scenario; +using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; +using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; +using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; +using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; +using ::WIFI_POWER_SCENARIO_VOICE_CALL; +using ::wifi_radio_combination; +using ::wifi_radio_combination_matrix; +using ::wifi_radio_configuration; +using ::wifi_rate; +using ::wifi_request_id; +using ::wifi_ring_buffer_status; +using ::wifi_roaming_capabilities; +using ::wifi_roaming_config; +using ::wifi_rtt_bw; +using ::WIFI_RTT_BW_10; +using ::WIFI_RTT_BW_160; +using ::WIFI_RTT_BW_20; +using ::WIFI_RTT_BW_320; +using ::WIFI_RTT_BW_40; +using ::WIFI_RTT_BW_5; +using ::WIFI_RTT_BW_80; +using ::wifi_rtt_capabilities; +using ::wifi_rtt_config; +using ::wifi_rtt_preamble; +using ::WIFI_RTT_PREAMBLE_EHT; +using ::WIFI_RTT_PREAMBLE_HE; +using ::WIFI_RTT_PREAMBLE_HT; +using ::WIFI_RTT_PREAMBLE_LEGACY; +using ::WIFI_RTT_PREAMBLE_VHT; +using ::wifi_rtt_responder; +using ::wifi_rtt_result; +using ::wifi_rtt_status; +using ::wifi_rtt_type; +using ::wifi_rx_packet_fate; +using ::wifi_rx_report; +using ::wifi_scan_bucket_spec; +using ::wifi_scan_cmd_params; +using ::WIFI_SCAN_FLAG_INTERRUPTED; +using ::wifi_scan_result; +using ::WIFI_SUCCESS; +using ::wifi_tx_packet_fate; +using ::wifi_tx_report; +using ::wifi_usable_channel; +using ::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE; +using ::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY; +using ::WLAN_MAC_2_4_BAND; +using ::WLAN_MAC_5_0_BAND; +using ::WLAN_MAC_60_0_BAND; +using ::WLAN_MAC_6_0_BAND; + +// APF capabilities supported by the iface. +struct PacketFilterCapabilities { + uint32_t version; + uint32_t max_len; +}; + +// WARNING: We don't care about the variable sized members of either +// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma +// to escape the compiler warnings regarding this. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end" +// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in +// |wifi_radio_stat| structure in the legacy HAL API. Separate that out +// into a separate return element to avoid passing pointers around. +struct LinkLayerRadioStats { + wifi_radio_stat stats; + std::vector tx_time_per_levels; + std::vector channel_stats; +}; + +struct WifiPeerInfo { + wifi_peer_info peer_info; + std::vector rate_stats; +}; + +struct LinkLayerStats { + wifi_iface_stat iface; + std::vector radios; + std::vector peers; +}; +#pragma GCC diagnostic pop + +// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and +// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided +// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL +// API. Separate that out into a separate return elements to avoid passing +// pointers around. +struct WakeReasonStats { + WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt; + std::vector cmd_event_wake_cnt; + std::vector driver_fw_local_wake_cnt; +}; + +// NAN response and event callbacks struct. +struct NanCallbackHandlers { + // NotifyResponse invoked to notify the status of the Request. + std::function on_notify_response; + // Various event callbacks. + std::function on_event_publish_terminated; + std::function on_event_match; + std::function on_event_match_expired; + std::function on_event_subscribe_terminated; + std::function on_event_followup; + std::function on_event_disc_eng_event; + std::function on_event_disabled; + std::function on_event_tca; + std::function on_event_beacon_sdf_payload; + std::function on_event_data_path_request; + std::function on_event_data_path_confirm; + std::function on_event_data_path_end; + std::function on_event_transmit_follow_up; + std::function on_event_range_request; + std::function on_event_range_report; + std::function on_event_schedule_update; +}; + +// Full scan results contain IE info and are hence passed by reference, to +// preserve the variable length array member |ie_data|. Callee must not retain +// the pointer. +using on_gscan_full_result_callback = + std::function; +// These scan results don't contain any IE info, so no need to pass by +// reference. +using on_gscan_results_callback = + std::function&)>; + +// Invoked when the rssi value breaches the thresholds set. +using on_rssi_threshold_breached_callback = + std::function, int8_t)>; + +// Callback for RTT range request results. +// Rtt results contain IE info and are hence passed by reference, to +// preserve the |LCI| and |LCR| pointers. Callee must not retain +// the pointer. +using on_rtt_results_callback = + std::function&)>; + +// Callback for ring buffer data. +using on_ring_buffer_data_callback = std::function&, const wifi_ring_buffer_status&)>; + +// Callback for alerts. +using on_error_alert_callback = std::function&)>; + +// Callback for subsystem restart +using on_subsystem_restart_callback = std::function; + +// Struct for the mac info from the legacy HAL. This is a cleaner version +// of the |wifi_mac_info| & |wifi_iface_info|. +typedef struct { + std::string name; + wifi_channel channel; +} WifiIfaceInfo; + +typedef struct { + uint32_t wlan_mac_id; + /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */ + uint32_t mac_band; + /* Represents the connected Wi-Fi interfaces associated with each MAC */ + std::vector iface_infos; +} WifiMacInfo; + +// Callback for radio mode change +using on_radio_mode_change_callback = std::function&)>; + +// TWT response and event callbacks struct. +struct TwtCallbackHandlers { + // Callback for TWT setup response + std::function on_setup_response; + // Callback for TWT teardown completion + std::function on_teardown_completion; + // Callback for TWT info frame received event + std::function on_info_frame_received; + // Callback for TWT notification from the device + std::function on_device_notify; +}; + +// CHRE response and event callbacks struct. +struct ChreCallbackHandlers { + // Callback for CHRE NAN RTT + std::function on_wifi_chre_nan_rtt_state; +}; + +// Cached Scan Results response and event callbacks struct. +struct CachedScanResultsCallbackHandlers { + // Callback for Cached Scan Results + std::function on_cached_scan_results; +}; + +/** + * Class that encapsulates all legacy HAL interactions. + * This class manages the lifetime of the event loop thread used by legacy HAL. + * + * Note: There will only be a single instance of this class created in the Wifi + * object and will be valid for the lifetime of the process. + */ +class WifiLegacyHal { + public: + WifiLegacyHal(const std::weak_ptr iface_tool, const wifi_hal_fn& fn, + bool is_primary); + virtual ~WifiLegacyHal() = default; + + // Initialize the legacy HAL function table. + virtual wifi_error initialize(); + // Start the legacy HAL and the event looper thread. + virtual wifi_error start(); + // Deinitialize the legacy HAL and wait for the event loop thread to exit + // using a predefined timeout. + virtual wifi_error stop(std::unique_lock* lock, + const std::function& on_complete_callback); + virtual wifi_error waitForDriverReady(); + // Checks if legacy HAL has successfully started + bool isStarted(); + // Wrappers for all the functions in the legacy HAL function table. + virtual std::pair getDriverVersion(const std::string& iface_name); + virtual std::pair getFirmwareVersion(const std::string& iface_name); + std::pair> requestDriverMemoryDump( + const std::string& iface_name); + std::pair> requestFirmwareMemoryDump( + const std::string& iface_name); + virtual std::pair getSupportedFeatureSet(const std::string& iface_name); + // APF functions. + std::pair getPacketFilterCapabilities( + const std::string& iface_name); + wifi_error setPacketFilter(const std::string& iface_name, const std::vector& program); + std::pair> readApfPacketFilterData( + const std::string& iface_name); + // Gscan functions. + std::pair getGscanCapabilities( + const std::string& iface_name); + // These API's provides a simplified interface over the legacy Gscan API's: + // a) All scan events from the legacy HAL API other than the + // |WIFI_SCAN_FAILED| are treated as notification of results. + // This method then retrieves the cached scan results from the legacy + // HAL API and triggers the externally provided + // |on_results_user_callback| on success. + // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan + // results + // triggers the externally provided |on_failure_user_callback|. + // c) Full scan result event triggers the externally provided + // |on_full_result_user_callback|. + wifi_error startGscan(const std::string& iface_name, wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function& on_failure_callback, + const on_gscan_results_callback& on_results_callback, + const on_gscan_full_result_callback& on_full_result_callback); + wifi_error stopGscan(const std::string& iface_name, wifi_request_id id); + std::pair> getValidFrequenciesForBand( + const std::string& iface_name, wifi_band band); + virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on); + // Link layer stats functions. + wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug); + wifi_error disableLinkLayerStats(const std::string& iface_name); + std::pair getLinkLayerStats(const std::string& iface_name); + // RSSI monitor functions. + wifi_error startRssiMonitoring( + const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi, + const on_rssi_threshold_breached_callback& on_threshold_breached_callback); + wifi_error stopRssiMonitoring(const std::string& iface_name, wifi_request_id id); + std::pair getRoamingCapabilities( + const std::string& iface_name); + wifi_error configureRoaming(const std::string& iface_name, const wifi_roaming_config& config); + wifi_error enableFirmwareRoaming(const std::string& iface_name, fw_roaming_state_t state); + wifi_error configureNdOffload(const std::string& iface_name, bool enable); + wifi_error startSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id, + uint16_t ether_type, + const std::vector& ip_packet_data, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms); + wifi_error stopSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id); + virtual wifi_error selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario); + virtual wifi_error resetTxPowerScenario(const std::string& iface_name); + wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode); + wifi_error setThermalMitigationMode(wifi_thermal_mode mode, uint32_t completion_window); + wifi_error setDscpToAccessCategoryMapping(uint32_t start, uint32_t end, + uint32_t access_category); + wifi_error resetDscpToAccessCategoryMapping(); + // Logger/debug functions. + std::pair getLoggerSupportedFeatureSet(const std::string& iface_name); + wifi_error startPktFateMonitoring(const std::string& iface_name); + std::pair> getTxPktFates(const std::string& iface_name); + std::pair> getRxPktFates(const std::string& iface_name); + std::pair getWakeReasonStats(const std::string& iface_name); + wifi_error registerRingBufferCallbackHandler( + const std::string& iface_name, const on_ring_buffer_data_callback& on_data_callback); + wifi_error deregisterRingBufferCallbackHandler(const std::string& iface_name); + virtual wifi_error registerSubsystemRestartCallbackHandler( + const on_subsystem_restart_callback& on_restart_callback); + std::pair> getRingBuffersStatus( + const std::string& iface_name); + wifi_error startRingBufferLogging(const std::string& iface_name, const std::string& ring_name, + uint32_t verbose_level, uint32_t max_interval_sec, + uint32_t min_data_size); + wifi_error getRingBufferData(const std::string& iface_name, const std::string& ring_name); + wifi_error registerErrorAlertCallbackHandler(const std::string& iface_name, + const on_error_alert_callback& on_alert_callback); + wifi_error deregisterErrorAlertCallbackHandler(const std::string& iface_name); + // Radio mode functions. + virtual wifi_error registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback); + // RTT functions. + wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id, + const std::vector& rtt_configs, + const on_rtt_results_callback& on_results_callback); + wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id, + const std::vector>& mac_addrs); + std::pair getRttCapabilities(const std::string& iface_name); + std::pair getRttResponderInfo(const std::string& iface_name); + wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id, + const wifi_channel_info& channel_hint, uint32_t max_duration_secs, + const wifi_rtt_responder& info); + wifi_error disableRttResponder(const std::string& iface_name, wifi_request_id id); + wifi_error setRttLci(const std::string& iface_name, wifi_request_id id, + const wifi_lci_information& info); + wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id, + const wifi_lcr_information& info); + // NAN functions. + virtual wifi_error nanRegisterCallbackHandlers(const std::string& iface_name, + const NanCallbackHandlers& callbacks); + wifi_error nanEnableRequest(const std::string& iface_name, transaction_id id, + const NanEnableRequest& msg); + virtual wifi_error nanDisableRequest(const std::string& iface_name, transaction_id id); + wifi_error nanPublishRequest(const std::string& iface_name, transaction_id id, + const NanPublishRequest& msg); + wifi_error nanPublishCancelRequest(const std::string& iface_name, transaction_id id, + const NanPublishCancelRequest& msg); + wifi_error nanSubscribeRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeRequest& msg); + wifi_error nanSubscribeCancelRequest(const std::string& iface_name, transaction_id id, + const NanSubscribeCancelRequest& msg); + wifi_error nanTransmitFollowupRequest(const std::string& iface_name, transaction_id id, + const NanTransmitFollowupRequest& msg); + wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id, + const NanStatsRequest& msg); + wifi_error nanConfigRequest(const std::string& iface_name, transaction_id id, + const NanConfigRequest& msg); + wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id, + const NanTCARequest& msg); + wifi_error nanBeaconSdfPayloadRequest(const std::string& iface_name, transaction_id id, + const NanBeaconSdfPayloadRequest& msg); + std::pair nanGetVersion(); + wifi_error nanGetCapabilities(const std::string& iface_name, transaction_id id); + wifi_error nanDataInterfaceCreate(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name); + virtual wifi_error nanDataInterfaceDelete(const std::string& iface_name, transaction_id id, + const std::string& data_iface_name); + wifi_error nanDataRequestInitiator(const std::string& iface_name, transaction_id id, + const NanDataPathInitiatorRequest& msg); + wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id, + const NanDataPathIndicationResponse& msg); + wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId); + // AP functions. + wifi_error setCountryCode(const std::string& iface_name, std::array code); + + // interface functions. + virtual wifi_error createVirtualInterface(const std::string& ifname, + wifi_interface_type iftype); + virtual wifi_error deleteVirtualInterface(const std::string& ifname); + virtual wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname); + + // STA + STA functions + virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname); + virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case); + + // Coex functions. + virtual wifi_error setCoexUnsafeChannels(std::vector unsafe_channels, + uint32_t restrictions); + + wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode); + + wifi_error twtRegisterHandler(const std::string& iface_name, + const TwtCallbackHandlers& handler); + + std::pair twtGetCapability(const std::string& iface_name); + + wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg); + + wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg); + + wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg); + + std::pair twtGetStats(const std::string& iface_name, uint8_t configId); + + wifi_error twtClearStats(const std::string& iface_name, uint8_t configId); + + wifi_error setDtimConfig(const std::string& iface_name, uint32_t multiplier); + + // Retrieve the list of usable channels in the requested bands + // for the requested modes + std::pair> getUsableChannels( + uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask); + + wifi_error triggerSubsystemRestart(); + + wifi_error setIndoorState(bool isIndoor); + + std::pair getSupportedRadioCombinationsMatrix(); + + // CHRE NAN RTT function + wifi_error chreNanRttRequest(const std::string& iface_name, bool enable); + + wifi_error chreRegisterHandler(const std::string& iface_name, + const ChreCallbackHandlers& handler); + + wifi_error enableWifiTxPowerLimits(const std::string& iface_name, bool enable); + wifi_error getWifiCachedScanResults(const std::string& iface_name, + const CachedScanResultsCallbackHandlers& handler); + + private: + // Retrieve interface handles for all the available interfaces. + wifi_error retrieveIfaceHandles(); + wifi_interface_handle getIfaceHandle(const std::string& iface_name); + // Run the legacy HAL event loop thread. + void runEventLoop(); + // Retrieve the cached gscan results to pass the results back to the + // external callbacks. + std::pair> getGscanCachedResults( + const std::string& iface_name); + void invalidate(); + // Handles wifi (error) status of Virtual interface create/delete + wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname, + wifi_error status); + + // Global function table of legacy HAL. + wifi_hal_fn global_func_table_; + // Opaque handle to be used for all global operations. + wifi_handle global_handle_; + // Map of interface name to handle that is to be used for all interface + // specific operations. + std::map iface_name_to_handle_; + // Flag to indicate if we have initiated the cleanup of legacy HAL. + std::atomic awaiting_event_loop_termination_; + std::condition_variable_any stop_wait_cv_; + // Flag to indicate if the legacy HAL has been started. + bool is_started_; + std::weak_ptr iface_tool_; + // flag to indicate if this HAL is for the primary chip. This is used + // in order to avoid some hard-coded behavior used with older HALs, + // such as bring wlan0 interface up/down on start/stop HAL. + // it may be removed once vendor HALs are updated. + bool is_primary_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp new file mode 100644 index 0000000..147bf4d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "wifi_legacy_hal_factory.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals"; +static constexpr char kVendorHalsDescExt[] = ".xml"; +static constexpr uint32_t kVendorHalsDescVersion = 1; + +bool isDirectory(struct dirent* entryPtr) { + bool isDir = false; + if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) { + isDir = (entryPtr->d_type == DT_DIR); + } else { + struct stat entryStat; + stat(entryPtr->d_name, &entryStat); + isDir = S_ISDIR(entryStat.st_mode); + } + return isDir; +} + +bool isFileExtension(const char* name, const char* ext) { + if (name == NULL) return false; + if (ext == NULL) return false; + + size_t extLen = strlen(ext); + size_t nameLen = strlen(name); + + if (extLen > nameLen) return false; + + if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false; + + return true; +} +}; // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { + +WifiLegacyHalFactory::WifiLegacyHalFactory( + const std::weak_ptr iface_tool) + : iface_tool_(iface_tool) {} + +std::vector> WifiLegacyHalFactory::getHals() { + if (legacy_hals_.empty()) { + if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList(); + for (auto& desc : descs_) { + std::shared_ptr hal = + std::make_shared(iface_tool_, desc.fn, desc.primary); + legacy_hals_.push_back(hal); + } + } + + return legacy_hals_; +} + +bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() { + wifi_hal_lib_desc desc; + + if (!initLinkedHalFunctionTable(&desc.fn)) return false; + + desc.primary = true; + desc.handle = NULL; + descs_.push_back(desc); + return true; +} + +bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) { + init_wifi_vendor_hal_func_table_t initfn; + + initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT, + "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(INFO) << "no vendor HAL library linked, will try dynamic load"; + return false; + } + + if (!initHalFuncTableWithStubs(hal_fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + return false; + } + + if (initfn(hal_fn) != WIFI_SUCCESS) { + LOG(ERROR) << "Can not initialize the vendor function pointer table"; + return false; + } + + return true; +} + +/* + * Overall structure of the HAL descriptor XML schema + * + * + * + * /vendor/lib64/libwifi-hal-qcom.so + * 1 + * + */ +void WifiLegacyHalFactory::initVendorHalsDescriptorList() { + xmlDocPtr xml; + xmlNodePtr node, cnode; + char* version; + std::string path; + xmlChar* value; + wifi_hal_lib_desc desc; + + LOG(INFO) << "processing vendor HALs descriptions in " << kVendorHalsDescPath; + DIR* dirPtr = ::opendir(kVendorHalsDescPath); + if (dirPtr == NULL) { + LOG(ERROR) << "failed to open " << kVendorHalsDescPath; + return; + } + for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL; + entryPtr = ::readdir(dirPtr)) { + if (isDirectory(entryPtr)) continue; + + if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt)) + continue; // only process .xml files + + LOG(INFO) << "processing config file: " << entryPtr->d_name; + + std::string fullPath(kVendorHalsDescPath); + fullPath.append("/"); + fullPath.append(entryPtr->d_name); + xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER); + if (!xml) { + LOG(ERROR) << "failed to parse: " << entryPtr->d_name << " skipping..."; + continue; + } + node = xmlDocGetRootElement(xml); + if (!node) { + LOG(ERROR) << "empty config file: " << entryPtr->d_name << " skipping..."; + goto skip; + } + if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) { + LOG(ERROR) << "bad config, root element not WifiVendorHal: " << entryPtr->d_name + << " skipping..."; + goto skip; + } + version = (char*)xmlGetProp(node, BAD_CAST "version"); + if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) { + LOG(ERROR) << "conf file: " << entryPtr->d_name + << "must have version: " << kVendorHalsDescVersion << ", skipping..."; + goto skip; + } + cnode = node->children; + path.clear(); + desc.primary = false; + while (cnode) { + if (!xmlStrcmp(cnode->name, BAD_CAST "path")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + if (value) path = (char*)value; + xmlFree(value); + } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) { + value = xmlNodeListGetString(xml, cnode->children, 1); + desc.primary = !xmlStrcmp(value, BAD_CAST "1"); + xmlFree(value); + } + cnode = cnode->next; + } + if (path.empty()) { + LOG(ERROR) << "hal library path not provided in: " << entryPtr->d_name + << ", skipping..."; + goto skip; + } + if (loadVendorHalLib(path, desc)) { + if (desc.primary) + descs_.insert(descs_.begin(), desc); + else + descs_.push_back(desc); + } + skip: + xmlFreeDoc(xml); + } + ::closedir(dirPtr); +} + +bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc) { + void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); + init_wifi_vendor_hal_func_table_t initfn; + wifi_error res; + + if (!h) { + LOG(ERROR) << "failed to open vendor hal library: " << path; + return false; + } + initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table"); + if (!initfn) { + LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path; + goto out_err; + } + + if (!initHalFuncTableWithStubs(&desc.fn)) { + LOG(ERROR) << "Can not initialize the basic function pointer table"; + goto out_err; + } + res = initfn(&desc.fn); + if (res != WIFI_SUCCESS) { + LOG(ERROR) << "failed to initialize the vendor func table in: " << path + << " error: " << res; + goto out_err; + } + + res = desc.fn.wifi_early_initialize(); + // vendor HALs which do not implement early_initialize will return + // WIFI_ERROR_NOT_SUPPORTED, treat this as success. + if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) { + LOG(ERROR) << "early initialization failed in: " << path << " error: " << res; + goto out_err; + } + + desc.handle = h; + return true; +out_err: + dlclose(h); + return false; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h new file mode 100644 index 0000000..9f4423e --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_factory.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 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 WIFI_LEGACY_HAL_FACTORY_H_ +#define WIFI_LEGACY_HAL_FACTORY_H_ + +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +// This is in a separate namespace to prevent typename conflicts between +// the legacy HAL types and the HIDL interface types. +namespace legacy_hal { +/** + * Class that creates WifiLegacyHal objects for vendor HALs in the system. + */ +class WifiLegacyHalFactory { + public: + WifiLegacyHalFactory(const std::weak_ptr iface_tool); + virtual ~WifiLegacyHalFactory() = default; + + std::vector> getHals(); + + private: + typedef struct { + wifi_hal_fn fn; + bool primary; + void* handle; + } wifi_hal_lib_desc; + + bool initVendorHalDescriptorFromLinked(); + void initVendorHalsDescriptorList(); + bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn); + bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc); + + std::weak_ptr iface_tool_; + std::vector descs_; + std::vector> legacy_hals_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_FACTORY_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp new file mode 100644 index 0000000..8f8527a --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wifi_legacy_hal_stubs.h" + +// TODO: Remove these stubs from HalTool in libwifi-system. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { +template +struct stubFunction; + +template +struct stubFunction { + static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; } +}; +template +struct stubFunction { + static constexpr void invoke(Args...) {} +}; + +template +void populateStubFor(T* val) { + *val = &stubFunction::invoke; +} + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { + if (hal_fn == nullptr) { + return false; + } + populateStubFor(&hal_fn->wifi_initialize); + populateStubFor(&hal_fn->wifi_wait_for_driver_ready); + populateStubFor(&hal_fn->wifi_cleanup); + populateStubFor(&hal_fn->wifi_event_loop); + populateStubFor(&hal_fn->wifi_get_error_info); + populateStubFor(&hal_fn->wifi_get_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_concurrency_matrix); + populateStubFor(&hal_fn->wifi_set_scanning_mac_oui); + populateStubFor(&hal_fn->wifi_get_supported_channels); + populateStubFor(&hal_fn->wifi_is_epr_supported); + populateStubFor(&hal_fn->wifi_get_ifaces); + populateStubFor(&hal_fn->wifi_get_iface_name); + populateStubFor(&hal_fn->wifi_set_iface_event_handler); + populateStubFor(&hal_fn->wifi_reset_iface_event_handler); + populateStubFor(&hal_fn->wifi_start_gscan); + populateStubFor(&hal_fn->wifi_stop_gscan); + populateStubFor(&hal_fn->wifi_get_cached_gscan_results); + populateStubFor(&hal_fn->wifi_set_bssid_hotlist); + populateStubFor(&hal_fn->wifi_reset_bssid_hotlist); + populateStubFor(&hal_fn->wifi_set_significant_change_handler); + populateStubFor(&hal_fn->wifi_reset_significant_change_handler); + populateStubFor(&hal_fn->wifi_get_gscan_capabilities); + populateStubFor(&hal_fn->wifi_set_link_stats); + populateStubFor(&hal_fn->wifi_get_link_stats); + populateStubFor(&hal_fn->wifi_clear_link_stats); + populateStubFor(&hal_fn->wifi_get_valid_channels); + populateStubFor(&hal_fn->wifi_rtt_range_request); + populateStubFor(&hal_fn->wifi_rtt_range_cancel); + populateStubFor(&hal_fn->wifi_get_rtt_capabilities); + populateStubFor(&hal_fn->wifi_rtt_get_responder_info); + populateStubFor(&hal_fn->wifi_enable_responder); + populateStubFor(&hal_fn->wifi_disable_responder); + populateStubFor(&hal_fn->wifi_set_nodfs_flag); + populateStubFor(&hal_fn->wifi_start_logging); + populateStubFor(&hal_fn->wifi_set_epno_list); + populateStubFor(&hal_fn->wifi_reset_epno_list); + populateStubFor(&hal_fn->wifi_set_country_code); + populateStubFor(&hal_fn->wifi_get_firmware_memory_dump); + populateStubFor(&hal_fn->wifi_set_log_handler); + populateStubFor(&hal_fn->wifi_reset_log_handler); + populateStubFor(&hal_fn->wifi_set_alert_handler); + populateStubFor(&hal_fn->wifi_reset_alert_handler); + populateStubFor(&hal_fn->wifi_get_firmware_version); + populateStubFor(&hal_fn->wifi_get_ring_buffers_status); + populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_ring_data); + populateStubFor(&hal_fn->wifi_enable_tdls); + populateStubFor(&hal_fn->wifi_disable_tdls); + populateStubFor(&hal_fn->wifi_get_tdls_status); + populateStubFor(&hal_fn->wifi_get_tdls_capabilities); + populateStubFor(&hal_fn->wifi_get_driver_version); + populateStubFor(&hal_fn->wifi_set_passpoint_list); + populateStubFor(&hal_fn->wifi_reset_passpoint_list); + populateStubFor(&hal_fn->wifi_set_lci); + populateStubFor(&hal_fn->wifi_set_lcr); + populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_start_rssi_monitoring); + populateStubFor(&hal_fn->wifi_stop_rssi_monitoring); + populateStubFor(&hal_fn->wifi_get_wake_reason_stats); + populateStubFor(&hal_fn->wifi_configure_nd_offload); + populateStubFor(&hal_fn->wifi_get_driver_memory_dump); + populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring); + populateStubFor(&hal_fn->wifi_get_tx_pkt_fates); + populateStubFor(&hal_fn->wifi_get_rx_pkt_fates); + populateStubFor(&hal_fn->wifi_nan_enable_request); + populateStubFor(&hal_fn->wifi_nan_disable_request); + populateStubFor(&hal_fn->wifi_nan_publish_request); + populateStubFor(&hal_fn->wifi_nan_publish_cancel_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request); + populateStubFor(&hal_fn->wifi_nan_transmit_followup_request); + populateStubFor(&hal_fn->wifi_nan_stats_request); + populateStubFor(&hal_fn->wifi_nan_config_request); + populateStubFor(&hal_fn->wifi_nan_tca_request); + populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request); + populateStubFor(&hal_fn->wifi_nan_register_handler); + populateStubFor(&hal_fn->wifi_nan_get_version); + populateStubFor(&hal_fn->wifi_nan_get_capabilities); + populateStubFor(&hal_fn->wifi_nan_data_interface_create); + populateStubFor(&hal_fn->wifi_nan_data_interface_delete); + populateStubFor(&hal_fn->wifi_nan_data_request_initiator); + populateStubFor(&hal_fn->wifi_nan_data_indication_response); + populateStubFor(&hal_fn->wifi_nan_data_end); + populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities); + populateStubFor(&hal_fn->wifi_set_packet_filter); + populateStubFor(&hal_fn->wifi_read_packet_filter); + populateStubFor(&hal_fn->wifi_get_roaming_capabilities); + populateStubFor(&hal_fn->wifi_enable_firmware_roaming); + populateStubFor(&hal_fn->wifi_configure_roaming); + populateStubFor(&hal_fn->wifi_select_tx_power_scenario); + populateStubFor(&hal_fn->wifi_reset_tx_power_scenario); + populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler); + populateStubFor(&hal_fn->wifi_set_latency_mode); + populateStubFor(&hal_fn->wifi_set_thermal_mitigation_mode); + populateStubFor(&hal_fn->wifi_virtual_interface_create); + populateStubFor(&hal_fn->wifi_virtual_interface_delete); + populateStubFor(&hal_fn->wifi_map_dscp_access_category); + populateStubFor(&hal_fn->wifi_reset_dscp_mapping); + populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler); + populateStubFor(&hal_fn->wifi_get_supported_iface_name); + populateStubFor(&hal_fn->wifi_early_initialize); + populateStubFor(&hal_fn->wifi_get_chip_feature_set); + populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection); + populateStubFor(&hal_fn->wifi_multi_sta_set_use_case); + populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels); + populateStubFor(&hal_fn->wifi_set_voip_mode); + populateStubFor(&hal_fn->wifi_twt_register_handler); + populateStubFor(&hal_fn->wifi_twt_get_capability); + populateStubFor(&hal_fn->wifi_twt_setup_request); + populateStubFor(&hal_fn->wifi_twt_teardown_request); + populateStubFor(&hal_fn->wifi_twt_info_frame_request); + populateStubFor(&hal_fn->wifi_twt_get_stats); + populateStubFor(&hal_fn->wifi_twt_clear_stats); + populateStubFor(&hal_fn->wifi_set_dtim_config); + populateStubFor(&hal_fn->wifi_get_usable_channels); + populateStubFor(&hal_fn->wifi_trigger_subsystem_restart); + populateStubFor(&hal_fn->wifi_set_indoor_state); + populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix); + populateStubFor(&hal_fn->wifi_nan_rtt_chre_enable_request); + populateStubFor(&hal_fn->wifi_nan_rtt_chre_disable_request); + populateStubFor(&hal_fn->wifi_chre_register_handler); + populateStubFor(&hal_fn->wifi_enable_tx_power_limits); + populateStubFor(&hal_fn->wifi_get_cached_scan_results); + return true; +} +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h new file mode 100644 index 0000000..ebc0347 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_legacy_hal_stubs.h @@ -0,0 +1,37 @@ +/* + * 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 WIFI_LEGACY_HAL_STUBS_H_ +#define WIFI_LEGACY_HAL_STUBS_H_ + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace legacy_hal { + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_STUBS_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp new file mode 100644 index 0000000..4b8ac7d --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "wifi_mode_controller.h" + +using android::hardware::wifi::V1_0::IfaceType; +using android::wifi_hal::DriverTool; + +namespace { +int convertIfaceTypeToFirmwareMode(IfaceType type) { + int mode; + switch (type) { + case IfaceType::AP: + mode = DriverTool::kFirmwareModeAp; + break; + case IfaceType::P2P: + mode = DriverTool::kFirmwareModeP2p; + break; + case IfaceType::NAN: + // NAN is exposed in STA mode currently. + mode = DriverTool::kFirmwareModeSta; + break; + case IfaceType::STA: + mode = DriverTool::kFirmwareModeSta; + break; + } + return mode; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace mode_controller { + +WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {} + +bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) { + return driver_tool_->IsFirmwareModeChangeNeeded(convertIfaceTypeToFirmwareMode(type)); +} + +bool WifiModeController::initialize() { + if (!driver_tool_->LoadDriver()) { + LOG(ERROR) << "Failed to load WiFi driver"; + return false; + } + return true; +} + +bool WifiModeController::changeFirmwareMode(IfaceType type) { + if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) { + LOG(ERROR) << "Failed to change firmware mode"; + return false; + } + return true; +} + +bool WifiModeController::deinitialize() { + if (!driver_tool_->UnloadDriver()) { + LOG(ERROR) << "Failed to unload WiFi driver"; + return false; + } + return true; +} +} // namespace mode_controller +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h new file mode 100644 index 0000000..fee2b66 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_mode_controller.h @@ -0,0 +1,63 @@ +/* + * 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 WIFI_MODE_CONTROLLER_H_ +#define WIFI_MODE_CONTROLLER_H_ + +#include + +#include + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +namespace mode_controller { +using namespace android::hardware::wifi::V1_0; + +/** + * Class that encapsulates all firmware mode configuration. + * This class will perform the necessary firmware reloads to put the chip in the + * required state (essentially a wrapper over DriverTool). + */ +class WifiModeController { + public: + WifiModeController(); + virtual ~WifiModeController() = default; + + // Checks if a firmware mode change is necessary to support the specified + // iface type operations. + virtual bool isFirmwareModeChangeNeeded(IfaceType type); + virtual bool initialize(); + // Change the firmware mode to support the specified iface type operations. + virtual bool changeFirmwareMode(IfaceType type); + // Unload the driver. This should be invoked whenever |IWifi.stop()| is + // invoked. + virtual bool deinitialize(); + + private: + std::unique_ptr driver_tool_; +}; + +} // namespace mode_controller +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_MODE_CONTROLLER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp new file mode 100644 index 0000000..4c61ba7 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.cpp @@ -0,0 +1,1018 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_nan_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiNanIface::WifiNanIface(const std::string& ifname, bool is_dedicated_iface, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), + is_dedicated_iface_(is_dedicated_iface), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { + if (is_dedicated_iface_) { + // If using a dedicated iface, set the iface up first. + if (!iface_util_.lock()->setUpState(ifname_, true)) { + // Fatal failure, invalidate the iface object. + invalidate(); + return; + } + } + // Register all the callbacks here. these should be valid for the lifetime + // of the object. Whenever the mode changes legacy HAL will remove + // all of these callbacks. + legacy_hal::NanCallbackHandlers callback_handlers; + android::wp weak_ptr_this(this); + + // Callback for response. + callback_handlers.on_notify_response = [weak_ptr_this](legacy_hal::transaction_id id, + const legacy_hal::NanResponseMsg& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus wifiNanStatus; + if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg, &wifiNanStatus)) { + LOG(ERROR) << "Failed to convert nan response header"; + return; + } + + switch (msg.response_type) { + case legacy_hal::NAN_RESPONSE_ENABLED: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyEnableResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_DISABLED: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyDisableResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStartPublishResponse(id, wifiNanStatus, + msg.body.publish_response.publish_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStopPublishResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyTransmitFollowupResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStartSubscribeResponse( + id, wifiNanStatus, + msg.body.subscribe_response.subscribe_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStopSubscribeResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_CONFIG: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyConfigResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_GET_CAPABILITIES: { + V1_6::NanCapabilities hidl_struct; + if (!hidl_struct_util::convertLegacyNanCapabilitiesResponseToHidl( + msg.body.nan_capabilities, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) { + if (!callback->notifyCapabilitiesResponse_1_6(id, wifiNanStatus, hidl_struct) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_CREATE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyCreateDataInterfaceResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_DELETE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyDeleteDataInterfaceResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INITIATOR_RESPONSE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyInitiateDataPathResponse( + id, wifiNanStatus, + msg.body.data_request_response.ndp_instance_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_RESPONDER_RESPONSE: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyRespondToDataPathIndicationResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_END: { + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyTerminateDataPathResponse(id, wifiNanStatus).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD: + /* fall through */ + case legacy_hal::NAN_RESPONSE_TCA: + /* fall through */ + case legacy_hal::NAN_RESPONSE_STATS: + /* fall through */ + case legacy_hal::NAN_RESPONSE_ERROR: + /* fall through */ + default: + LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type; + return; + } + }; + + callback_handlers.on_event_disc_eng_event = + [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanClusterEventInd hidl_struct; + // event types defined identically - hence can be cast + hidl_struct.eventType = (NanClusterEventType)msg.event_type; + hidl_struct.addr = msg.data.mac_addr.addr; + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventClusterEvent(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_disabled = [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason), + &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_publish_terminated = + [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, + sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_subscribe_terminated = + [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, + sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match = [weak_ptr_this](const legacy_hal::NanMatchInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + V1_6::NanMatchInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) { + if (!callback->eventMatch_1_6(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match_expired = [weak_ptr_this]( + const legacy_hal::NanMatchExpiredInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventMatchExpired(msg.publish_subscribe_id, msg.requestor_instance_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_followup = [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanFollowupReceivedInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventFollowupReceived(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_transmit_follow_up = + [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, + sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventTransmitFollowup(msg.id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_request = + [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanDataPathRequestInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(msg, + &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDataPathRequest(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_confirm = + [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + V1_6::NanDataPathConfirmInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(msg, + &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) { + if (!callback->eventDataPathConfirm_1_6(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_end = + [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + for (int i = 0; i < msg.num_ndp_instances; ++i) { + if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + } + }; + + callback_handlers.on_event_beacon_sdf_payload = + [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) { + LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called"; + }; + + callback_handlers.on_event_range_request = + [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) { + LOG(ERROR) << "on_event_range_request - should not be called"; + }; + + callback_handlers.on_event_range_report = + [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) { + LOG(ERROR) << "on_event_range_report - should not be called"; + }; + + callback_handlers.on_event_schedule_update = + [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + V1_6::NanDataPathScheduleUpdateInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) { + if (!callback->eventDataPathScheduleUpdate_1_6(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to register nan callbacks. Invalidating object"; + invalidate(); + } + + // Register for iface state toggle events. + iface_util::IfaceEventHandlers event_handlers = {}; +#ifndef WIFI_SKIP_STATE_TOGGLE_OFF_ON_FOR_NAN + event_handlers.on_state_toggle_off_on = [weak_ptr_this](const std::string& /* iface_name */) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + // Tell framework that NAN has been disabled. + WifiNanStatus status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; +#endif + iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers); +} + +void WifiNanIface::invalidate() { + if (!isValid()) { + return; + } + // send commands to HAL to actually disable and destroy interfaces + legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0"); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1"); + iface_util_.lock()->unregisterIfaceEventHandlers(ifname_); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + event_cb_handler_1_2_.invalidate(); + event_cb_handler_1_5_.invalidate(); + is_valid_ = false; + if (is_dedicated_iface_) { + // If using a dedicated iface, set the iface down. + iface_util_.lock()->setUpState(ifname_, false); + } +} + +bool WifiNanIface::isValid() { + return is_valid_; +} + +std::string WifiNanIface::getName() { + return ifname_; +} + +std::set> WifiNanIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +std::set> WifiNanIface::getEventCallbacks_1_2() { + return event_cb_handler_1_2_.getCallbacks(); +} + +std::set> WifiNanIface::getEventCallbacks_1_5() { + return event_cb_handler_1_5_.getCallbacks(); +} + +std::set> WifiNanIface::getEventCallbacks_1_6() { + return event_cb_handler_1_6_.getCallbacks(); +} + +Return WifiNanIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getNameInternal, hidl_status_cb); +} + +Return WifiNanIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getTypeInternal, hidl_status_cb); +} + +Return WifiNanIface::registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallbackInternal, hidl_status_cb, callback); +} + +Return WifiNanIface::getCapabilitiesRequest(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequestInternal, hidl_status_cb, cmd_id); +} + +Return WifiNanIface::enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return WifiNanIface::configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + configRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return WifiNanIface::disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::disableRequestInternal, hidl_status_cb, cmd_id); +} + +Return WifiNanIface::startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequestInternal, hidl_status_cb, cmd_id, msg); +} + +Return WifiNanIface::stopPublishRequest(uint16_t cmd_id, uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopPublishRequestInternal, hidl_status_cb, cmd_id, + sessionId); +} + +Return WifiNanIface::startSubscribeRequest(uint16_t cmd_id, + const V1_0::NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startSubscribeRequestInternal, hidl_status_cb, cmd_id, + msg); +} + +Return WifiNanIface::stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopSubscribeRequestInternal, hidl_status_cb, cmd_id, + sessionId); +} + +Return WifiNanIface::transmitFollowupRequest(uint16_t cmd_id, + const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::transmitFollowupRequestInternal, hidl_status_cb, cmd_id, + msg); +} + +Return WifiNanIface::createDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::createDataInterfaceRequestInternal, hidl_status_cb, + cmd_id, iface_name); +} + +Return WifiNanIface::deleteDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::deleteDataInterfaceRequestInternal, hidl_status_cb, + cmd_id, iface_name); +} + +Return WifiNanIface::initiateDataPathRequest(uint16_t cmd_id, + const V1_0::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequestInternal, hidl_status_cb, cmd_id, + msg); +} + +Return WifiNanIface::respondToDataPathIndicationRequest( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return WifiNanIface::terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::terminateDataPathRequestInternal, hidl_status_cb, cmd_id, + ndpInstanceId); +} + +Return WifiNanIface::registerEventCallback_1_2( + const sp& callback, + registerEventCallback_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_2Internal, hidl_status_cb, + callback); +} + +Return WifiNanIface::enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_2Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_2Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_4Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_4Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::registerEventCallback_1_5( + const sp& callback, + registerEventCallback_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_5Internal, hidl_status_cb, + callback); +} + +Return WifiNanIface::enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_5Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_5Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::getCapabilitiesRequest_1_5( + uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequest_1_5Internal, hidl_status_cb, + cmd_id); +} + +Return WifiNanIface::enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_6Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_6Internal, hidl_status_cb, cmd_id, msg1, + msg2); +} + +Return WifiNanIface::initiateDataPathRequest_1_6(uint16_t cmd_id, + const V1_6::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequest_1_6Internal, hidl_status_cb, + cmd_id, msg); +} + +Return WifiNanIface::respondToDataPathIndicationRequest_1_6( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequest_1_6Internal, + hidl_status_cb, cmd_id, msg); +} + +Return WifiNanIface::startPublishRequest_1_6(uint16_t cmd_id, + const V1_6::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequest_1_6Internal, hidl_status_cb, cmd_id, + msg); +} + +std::pair WifiNanIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiNanIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN}; +} + +Return WifiNanIface::registerEventCallback_1_6( + const sp& callback, + registerEventCallback_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_6Internal, hidl_status_cb, + callback); +} + +WifiStatus WifiNanIface::registerEventCallbackInternal( + const sp& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanEnableRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanConfigRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t /* cmd_id */, + const V1_0::NanPublishRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId) { + legacy_hal::NanPublishCancelRequest legacy_msg; + legacy_msg.publish_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startSubscribeRequestInternal(uint16_t cmd_id, + const V1_0::NanSubscribeRequest& msg) { + legacy_hal::NanSubscribeRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId) { + legacy_hal::NanSubscribeCancelRequest legacy_msg; + legacy_msg.subscribe_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::transmitFollowupRequestInternal(uint16_t cmd_id, + const NanTransmitFollowupRequest& msg) { + legacy_hal::NanTransmitFollowupRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::createDataInterfaceRequestInternal(uint16_t cmd_id, + const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(uint16_t cmd_id, + const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::initiateDataPathRequestInternal( + uint16_t cmd_id, const V1_0::NanInitiateDataPathRequest& msg) { + legacy_hal::NanDataPathInitiatorRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg) { + legacy_hal::NanDataPathIndicationResponse legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::registerEventCallback_1_2Internal( + const sp& callback) { + sp callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_2_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::enableRequest_1_2Internal( + uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_2Internal( + uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequest_1_4Internal( + uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_4Internal( + uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */, + const V1_2::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::registerEventCallback_1_5Internal( + const sp& callback) { + sp callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp callback_1_2 = callback; + if (!event_cb_handler_1_2_.addCallback(callback_1_2)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_5_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::enableRequest_1_5Internal( + uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */, + const V1_5::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequest_1_5Internal( + uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */, + const V1_5::NanConfigRequestSupplemental& /* msg2 */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::enableRequest_1_6Internal(uint16_t cmd_id, + const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanEnableRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanEnableRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::configRequest_1_6Internal(uint16_t cmd_id, + const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanConfigRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanConfigRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::initiateDataPathRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg) { + legacy_hal::NanDataPathInitiatorRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequest_1_6ToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::respondToDataPathIndicationRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg) { + legacy_hal::NanDataPathIndicationResponse legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathIndicationResponse_1_6ToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequest_1_6Internal(uint16_t cmd_id, + const V1_6::NanPublishRequest& msg) { + legacy_hal::NanPublishRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::registerEventCallback_1_6Internal( + const sp& callback) { + sp callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp callback_1_2 = callback; + if (!event_cb_handler_1_2_.addCallback(callback_1_2)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + sp callback_1_5 = callback; + if (!event_cb_handler_1_5_.addCallback(callback_1_5)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_6_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h new file mode 100644 index 0000000..15bf572 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_nan_iface.h @@ -0,0 +1,208 @@ +/* + * 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 WIFI_NAN_IFACE_H_ +#define WIFI_NAN_IFACE_H_ + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; +using namespace android::hardware::wifi::V1_2; +using namespace android::hardware::wifi::V1_4; +using namespace android::hardware::wifi::V1_6; + +/** + * HIDL interface object used to control a NAN Iface instance. + */ +class WifiNanIface : public V1_6::IWifiNanIface { + public: + WifiNanIface(const std::string& ifname, bool is_dedicated_iface, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return registerEventCallback(const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilitiesRequest(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) override; + Return enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) override; + Return configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + configRequest_cb hidl_status_cb) override; + Return disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) override; + Return startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + Return stopPublishRequest(uint16_t cmd_id, uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) override; + Return startSubscribeRequest(uint16_t cmd_id, const V1_0::NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) override; + Return stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) override; + Return transmitFollowupRequest(uint16_t cmd_id, const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) override; + Return createDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) override; + Return deleteDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) override; + Return initiateDataPathRequest(uint16_t cmd_id, + const V1_0::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) override; + Return respondToDataPathIndicationRequest( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) override; + Return terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) override; + + Return registerEventCallback_1_2(const sp& callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) override; + Return configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) override; + Return enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_4_cb hidl_status_cb) override; + Return configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_4_cb hidl_status_cb) override; + Return registerEventCallback_1_5(const sp& callback, + registerEventCallback_1_5_cb hidl_status_cb) override; + Return enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + enableRequest_1_5_cb hidl_status_cb) override; + Return configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2, + configRequest_1_5_cb hidl_status_cb) override; + Return getCapabilitiesRequest_1_5(uint16_t cmd_id, + getCapabilitiesRequest_cb hidl_status_cb) override; + Return registerEventCallback_1_6(const sp& callback, + registerEventCallback_1_6_cb hidl_status_cb) override; + Return initiateDataPathRequest_1_6( + uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg, + initiateDataPathRequest_1_6_cb hidl_status_cb) override; + Return respondToDataPathIndicationRequest_1_6( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_1_6_cb hidl_status_cb) override; + Return enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + enableRequest_1_6_cb hidl_status_cb) override; + Return configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2, + configRequest_1_6_cb hidl_status_cb) override; + Return startPublishRequest_1_6(uint16_t cmd_id, const V1_6::NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus registerEventCallbackInternal(const sp& callback); + WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id); + WifiStatus enableRequestInternal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg); + WifiStatus configRequestInternal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg); + WifiStatus disableRequestInternal(uint16_t cmd_id); + WifiStatus startPublishRequestInternal(uint16_t cmd_id, const V1_0::NanPublishRequest& msg); + WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, const V1_0::NanSubscribeRequest& msg); + WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus transmitFollowupRequestInternal(uint16_t cmd_id, + const NanTransmitFollowupRequest& msg); + WifiStatus createDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name); + WifiStatus deleteDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name); + WifiStatus initiateDataPathRequestInternal(uint16_t cmd_id, + const V1_0::NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg); + WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId); + + WifiStatus registerEventCallback_1_2Internal( + const sp& callback); + WifiStatus enableRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus enableRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus registerEventCallback_1_5Internal( + const sp& callback); + WifiStatus enableRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_5::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_5::NanConfigRequestSupplemental& msg2); + WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id); + WifiStatus registerEventCallback_1_6Internal( + const sp& callback); + + WifiStatus enableRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1, + const V1_6::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg, + const V1_6::NanConfigRequestSupplemental& msg2); + WifiStatus startPublishRequest_1_6Internal(uint16_t cmd_id, const V1_6::NanPublishRequest& msg); + WifiStatus initiateDataPathRequest_1_6Internal(uint16_t cmd_id, + const V1_6::NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequest_1_6Internal( + uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg); + + // all 1_0 and descendant callbacks + std::set> getEventCallbacks(); + // all 1_2 and descendant callbacks + std::set> getEventCallbacks_1_2(); + // all 1_5 and descendant callbacks + std::set> getEventCallbacks_1_5(); + // all 1_6 and descendant callbacks + std::set> getEventCallbacks_1_6(); + + std::string ifname_; + bool is_dedicated_iface_; + std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_1_2_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_1_5_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_1_6_; + + DISALLOW_COPY_AND_ASSIGN(WifiNanIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_NAN_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp new file mode 100644 index 0000000..d4b1fca --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "wifi_p2p_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiP2pIface::WifiP2pIface(const std::string& ifname, + const std::weak_ptr legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiP2pIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiP2pIface::isValid() { + return is_valid_; +} + +std::string WifiP2pIface::getName() { + return ifname_; +} + +Return WifiP2pIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getNameInternal, hidl_status_cb); +} + +Return WifiP2pIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getTypeInternal, hidl_status_cb); +} + +std::pair WifiP2pIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiP2pIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P}; +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h new file mode 100644 index 0000000..0089443 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_p2p_iface.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WIFI_P2P_IFACE_H_ +#define WIFI_P2P_IFACE_H_ + +#include +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a P2P Iface instance. + */ +class WifiP2pIface : public V1_0::IWifiP2pIface { + public: + WifiP2pIface(const std::string& ifname, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + + std::string ifname_; + std::weak_ptr legacy_hal_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiP2pIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_P2P_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp new file mode 100644 index 0000000..aa9ee2f --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_rtt_controller.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiRttController::WifiRttController(const std::string& iface_name, + const sp& bound_iface, + const std::weak_ptr legacy_hal) + : ifname_(iface_name), bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiRttController::invalidate() { + legacy_hal_.reset(); + event_callbacks_.clear(); + is_valid_ = false; +} + +bool WifiRttController::isValid() { + return is_valid_; +} + +std::vector> WifiRttController::getEventCallbacks() { + return event_callbacks_; +} + +std::string WifiRttController::getIfaceName() { + return ifname_; +} + +Return WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getBoundIfaceInternal, hidl_status_cb); +} + +Return WifiRttController::registerEventCallback( + const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal, hidl_status_cb, + callback); +} + +Return WifiRttController::rangeRequest(uint32_t cmd_id, + const hidl_vec& rtt_configs, + rangeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal, hidl_status_cb, cmd_id, + rtt_configs); +} + +Return WifiRttController::rangeCancel(uint32_t cmd_id, + const hidl_vec>& addrs, + rangeCancel_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs); +} + +Return WifiRttController::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal, hidl_status_cb); +} + +Return WifiRttController::setLci(uint32_t cmd_id, const RttLciInformation& lci, + setLci_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci); +} + +Return WifiRttController::setLcr(uint32_t cmd_id, const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr); +} + +Return WifiRttController::getResponderInfo(getResponderInfo_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal, hidl_status_cb); +} + +Return WifiRttController::enableResponder(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_0::RttResponder& info, + enableResponder_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +Return WifiRttController::disableResponder(uint32_t cmd_id, + disableResponder_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id); +} + +Return WifiRttController::registerEventCallback_1_4( + const sp& callback, + registerEventCallback_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal_1_4, hidl_status_cb, + callback); +} + +Return WifiRttController::rangeRequest_1_4(uint32_t cmd_id, + const hidl_vec& rtt_configs, + rangeRequest_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal_1_4, hidl_status_cb, cmd_id, + rtt_configs); +} + +Return WifiRttController::getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal_1_4, hidl_status_cb); +} + +Return WifiRttController::getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal_1_4, hidl_status_cb); +} + +Return WifiRttController::enableResponder_1_4(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_4::RttResponder& info, + enableResponder_1_4_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal_1_4, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +Return WifiRttController::registerEventCallback_1_6( + const sp& callback, + registerEventCallback_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal_1_6, hidl_status_cb, + callback); +} + +Return WifiRttController::rangeRequest_1_6(uint32_t cmd_id, + const hidl_vec& rtt_configs, + rangeRequest_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal_1_6, hidl_status_cb, cmd_id, + rtt_configs); +} + +Return WifiRttController::getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal_1_6, hidl_status_cb); +} + +Return WifiRttController::getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal_1_6, hidl_status_cb); +} + +Return WifiRttController::enableResponder_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::RttResponder& info, + enableResponder_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal_1_6, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +std::pair> WifiRttController::getBoundIfaceInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal( + const sp& /* callback */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeRequestInternal( + uint32_t /* cmd_id */, const std::vector& /* rtt_configs */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeCancelInternal( + uint32_t cmd_id, const std::vector>& addrs) { + std::vector> legacy_addrs; + for (const auto& addr : addrs) { + legacy_addrs.push_back(addr); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, legacy_addrs); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiRttController::getCapabilitiesInternal() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id, const RttLciInformation& lci) { + legacy_hal::wifi_lci_information legacy_lci; + if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci, &legacy_lci)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr) { + legacy_hal::wifi_lcr_information legacy_lcr; + if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr, &legacy_lcr)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiRttController::getResponderInfoInternal() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiRttController::enableResponderInternal( + uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */, + uint32_t /* max_duration_seconds */, const V1_0::RttResponder& /* info */) { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)}; +} + +WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::registerEventCallbackInternal_1_4( + const sp& /* callback */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiRttController::rangeRequestInternal_1_4( + uint32_t /* cmd_id */, const std::vector& /* rtt_configs */) { + // Deprecated support for this api + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +std::pair WifiRttController::getCapabilitiesInternal_1_4() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair WifiRttController::getResponderInfoInternal_1_4() { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +WifiStatus WifiRttController::enableResponderInternal_1_4( + uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */, + uint32_t /* max_duration_seconds */, const V1_4::RttResponder& /* info */) { + // Deprecated support for this api + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal_1_6( + const sp& callback) { + // TODO(b/31632518): remove the callback when the client is destroyed + event_callbacks_.emplace_back(callback); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiRttController::rangeRequestInternal_1_6( + uint32_t cmd_id, const std::vector& rtt_configs) { + std::vector legacy_configs; + if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp weak_ptr_this(this); + const auto& on_results_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id, + const std::vector& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector hidl_results; + if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(results, + &hidl_results)) { + LOG(ERROR) << "Failed to convert rtt results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onResults_1_6(id, hidl_results).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest( + ifname_, cmd_id, legacy_configs, on_results_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiRttController::getCapabilitiesInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::RttCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair WifiRttController::getResponderInfoInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_responder legacy_responder; + std::tie(legacy_status, legacy_responder) = legacy_hal_.lock()->getRttResponderInfo(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::RttResponder hidl_responder; + if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, &hidl_responder)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder}; +} + +WifiStatus WifiRttController::enableResponderInternal_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::RttResponder& info) { + legacy_hal::wifi_channel_info legacy_channel_info; + if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(channel_hint, &legacy_channel_info)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_rtt_responder legacy_responder; + if (!hidl_struct_util::convertHidlRttResponderToLegacy(info, &legacy_responder)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder( + ifname_, cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder); + return createWifiStatusFromLegacyError(legacy_status); +} +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h new file mode 100644 index 0000000..fd5f68b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_rtt_controller.h @@ -0,0 +1,138 @@ +/* + * 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 WIFI_RTT_CONTROLLER_H_ +#define WIFI_RTT_CONTROLLER_H_ + +#include +#include +#include +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +/** + * HIDL interface object used to control all RTT operations. + */ +class WifiRttController : public V1_6::IWifiRttController { + public: + WifiRttController(const std::string& iface_name, const sp& bound_iface, + const std::weak_ptr legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::vector> getEventCallbacks(); + std::string getIfaceName(); + + // HIDL methods exposed. + Return getBoundIface(getBoundIface_cb hidl_status_cb) override; + Return registerEventCallback(const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return rangeRequest(uint32_t cmd_id, const hidl_vec& rtt_configs, + rangeRequest_cb hidl_status_cb) override; + Return rangeCancel(uint32_t cmd_id, const hidl_vec>& addrs, + rangeCancel_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return setLci(uint32_t cmd_id, const RttLciInformation& lci, + setLci_cb hidl_status_cb) override; + Return setLcr(uint32_t cmd_id, const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) override; + Return getResponderInfo(getResponderInfo_cb hidl_status_cb) override; + Return enableResponder(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_0::RttResponder& info, + enableResponder_cb hidl_status_cb) override; + Return disableResponder(uint32_t cmd_id, disableResponder_cb hidl_status_cb) override; + Return registerEventCallback_1_4( + const sp& callback, + registerEventCallback_1_4_cb hidl_status_cb) override; + Return rangeRequest_1_4(uint32_t cmd_id, const hidl_vec& rtt_configs, + rangeRequest_1_4_cb hidl_status_cb) override; + Return getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) override; + Return getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) override; + Return enableResponder_1_4(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_4::RttResponder& info, + enableResponder_1_4_cb hidl_status_cb) override; + Return registerEventCallback_1_6( + const sp& callback, + registerEventCallback_1_6_cb hidl_status_cb) override; + Return rangeRequest_1_6(uint32_t cmd_id, const hidl_vec& rtt_configs, + rangeRequest_1_6_cb hidl_status_cb) override; + Return getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) override; + Return getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) override; + Return enableResponder_1_6(uint32_t cmd_id, const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const V1_6::RttResponder& info, + enableResponder_1_6_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair> getBoundIfaceInternal(); + WifiStatus registerEventCallbackInternal( + const sp& callback); + WifiStatus rangeRequestInternal(uint32_t cmd_id, + const std::vector& rtt_configs); + WifiStatus rangeCancelInternal(uint32_t cmd_id, + const std::vector>& addrs); + std::pair getCapabilitiesInternal(); + WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci); + WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr); + std::pair getResponderInfoInternal(); + WifiStatus enableResponderInternal(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_0::RttResponder& info); + WifiStatus disableResponderInternal(uint32_t cmd_id); + WifiStatus registerEventCallbackInternal_1_4( + const sp& callback); + WifiStatus rangeRequestInternal_1_4(uint32_t cmd_id, + const std::vector& rtt_configs); + std::pair getCapabilitiesInternal_1_4(); + std::pair getResponderInfoInternal_1_4(); + WifiStatus enableResponderInternal_1_4(uint32_t cmd_id, + const V1_0::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_4::RttResponder& info); + WifiStatus registerEventCallbackInternal_1_6( + const sp& callback); + WifiStatus rangeRequestInternal_1_6(uint32_t cmd_id, + const std::vector& rtt_configs); + std::pair getCapabilitiesInternal_1_6(); + std::pair getResponderInfoInternal_1_6(); + WifiStatus enableResponderInternal_1_6(uint32_t cmd_id, + const V1_6::WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const V1_6::RttResponder& info); + + std::string ifname_; + sp bound_iface_; + std::weak_ptr legacy_hal_; + std::vector> event_callbacks_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiRttController); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_RTT_CONTROLLER_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp new file mode 100644 index 0000000..dd11839 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.cpp @@ -0,0 +1,592 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_sta_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiStaIface::WifiStaIface(const std::string& ifname, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util) + : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) { + // Turn on DFS channel usage for STA iface. + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, true); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable."; + } +} + +void WifiStaIface::invalidate() { + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiStaIface::isValid() { + return is_valid_; +} + +std::string WifiStaIface::getName() { + return ifname_; +} + +std::set> WifiStaIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return WifiStaIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getNameInternal, hidl_status_cb); +} + +Return WifiStaIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getTypeInternal, hidl_status_cb); +} + +Return WifiStaIface::registerEventCallback(const sp& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::registerEventCallbackInternal, hidl_status_cb, callback); +} + +Return WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getCapabilitiesInternal, hidl_status_cb); +} + +Return WifiStaIface::getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb); +} + +Return WifiStaIface::installApfPacketFilter(uint32_t cmd_id, const hidl_vec& program, + installApfPacketFilter_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::installApfPacketFilterInternal, hidl_status_cb, cmd_id, + program); +} + +Return WifiStaIface::readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::readApfPacketFilterDataInternal, hidl_status_cb); +} + +Return WifiStaIface::getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getBackgroundScanCapabilitiesInternal, hidl_status_cb); +} + +Return WifiStaIface::getValidFrequenciesForBand( + V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getValidFrequenciesForBandInternal, hidl_status_cb, band); +} + +Return WifiStaIface::startBackgroundScan(uint32_t cmd_id, + const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startBackgroundScanInternal, hidl_status_cb, cmd_id, + params); +} + +Return WifiStaIface::stopBackgroundScan(uint32_t cmd_id, + stopBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopBackgroundScanInternal, hidl_status_cb, cmd_id); +} + +Return WifiStaIface::enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb, + debug); +} + +Return WifiStaIface::disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb); +} + +Return WifiStaIface::getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal, hidl_status_cb); +} + +Return WifiStaIface::getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_3, hidl_status_cb); +} + +Return WifiStaIface::getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_5, hidl_status_cb); +} + +Return WifiStaIface::getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_6, hidl_status_cb); +} + +Return WifiStaIface::startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startRssiMonitoringInternal, hidl_status_cb, cmd_id, + max_rssi, min_rssi); +} + +Return WifiStaIface::stopRssiMonitoring(uint32_t cmd_id, + stopRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopRssiMonitoringInternal, hidl_status_cb, cmd_id); +} + +Return WifiStaIface::getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getRoamingCapabilitiesInternal, hidl_status_cb); +} + +Return WifiStaIface::configureRoaming(const StaRoamingConfig& config, + configureRoaming_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::configureRoamingInternal, hidl_status_cb, config); +} + +Return WifiStaIface::setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setRoamingStateInternal, hidl_status_cb, state); +} + +Return WifiStaIface::enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableNdOffloadInternal, hidl_status_cb, enable); +} + +Return WifiStaIface::startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec& ip_packet_data, uint16_t ether_type, + const hidl_array& src_address, const hidl_array& dst_address, + uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startSendingKeepAlivePacketsInternal, hidl_status_cb, + cmd_id, ip_packet_data, ether_type, src_address, dst_address, + period_in_ms); +} + +Return WifiStaIface::stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopSendingKeepAlivePacketsInternal, hidl_status_cb, + cmd_id); +} + +Return WifiStaIface::setScanningMacOui(const hidl_array& oui, + setScanningMacOui_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanningMacOuiInternal, hidl_status_cb, oui); +} + +Return WifiStaIface::startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb); +} + +Return WifiStaIface::getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugTxPacketFatesInternal, hidl_status_cb); +} + +Return WifiStaIface::getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugRxPacketFatesInternal, hidl_status_cb); +} + +Return WifiStaIface::setMacAddress(const hidl_array& mac, + setMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setMacAddressInternal, hidl_status_cb, mac); +} + +Return WifiStaIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getFactoryMacAddressInternal, hidl_status_cb); +} + +Return WifiStaIface::setScanMode(bool enable, setScanMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanModeInternal, hidl_status_cb, enable); +} + +std::pair WifiStaIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair WifiStaIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA}; +} + +WifiStatus WifiStaIface::registerEventCallbackInternal( + const sp& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair WifiStaIface::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + uint64_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + uint32_t legacy_logger_feature_set; + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // some devices don't support querying logger feature set + legacy_logger_feature_set = 0; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair +WifiStaIface::getApfPacketFilterCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::PacketFilterCapabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getPacketFilterCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaApfPacketFilterCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::installApfPacketFilterInternal(uint32_t /* cmd_id */, + const std::vector& program) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setPacketFilter(ifname_, program); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> WifiStaIface::readApfPacketFilterDataInternal() { + const std::pair> legacy_status_and_data = + legacy_hal_.lock()->readApfPacketFilterData(ifname_); + return {createWifiStatusFromLegacyError(legacy_status_and_data.first), + std::move(legacy_status_and_data.second)}; +} + +std::pair +WifiStaIface::getBackgroundScanCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_gscan_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getGscanCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaBackgroundScanCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair> +WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector valid_frequencies; + std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand( + ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} + +WifiStatus WifiStaIface::startBackgroundScanInternal(uint32_t cmd_id, + const StaBackgroundScanParameters& params) { + legacy_hal::wifi_scan_cmd_params legacy_params; + if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params, &legacy_params)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp weak_ptr_this(this); + const auto& on_failure_callback = [weak_ptr_this](legacy_hal::wifi_request_id id) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanFailure(id).isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback"; + } + } + }; + const auto& on_results_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id, + const std::vector& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector hidl_scan_datas; + if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl( + results, &hidl_scan_datas)) { + LOG(ERROR) << "Failed to convert scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanResults(id, hidl_scan_datas).isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback"; + } + } + }; + const auto& on_full_result_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const legacy_hal::wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + StaScanResult hidl_scan_result; + if (!hidl_struct_util::convertLegacyGscanResultToHidl(*result, true, &hidl_scan_result)) { + LOG(ERROR) << "Failed to convert full scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundFullScanResult(id, buckets_scanned, hidl_scan_result) + .isOk()) { + LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startGscan(ifname_, cmd_id, legacy_params, on_failure_callback, + on_results_callback, on_full_result_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableLinkLayerStats(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiStaIface::getLinkLayerStatsInternal() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair WifiStaIface::getLinkLayerStatsInternal_1_3() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair WifiStaIface::getLinkLayerStatsInternal_1_5() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair WifiStaIface::getLinkLayerStatsInternal_1_6() { + legacy_hal::wifi_error legacy_status; + legacy_hal::LinkLayerStats legacy_stats; + std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_6::StaLinkLayerStats hidl_stats; + if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, + int32_t min_rssi) { + android::wp weak_ptr_this(this); + const auto& on_threshold_breached_callback = [weak_ptr_this](legacy_hal::wifi_request_id id, + std::array bssid, + int8_t rssi) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) { + LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRssiMonitoring( + ifname_, cmd_id, max_rssi, min_rssi, on_threshold_breached_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair WifiStaIface::getRoamingCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_roaming_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRoamingCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaRoamingCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::configureRoamingInternal(const StaRoamingConfig& config) { + legacy_hal::wifi_roaming_config legacy_config; + if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config, &legacy_config)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->configureRoaming(ifname_, legacy_config); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableFirmwareRoaming( + ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->configureNdOffload(ifname_, enable); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, const std::vector& ip_packet_data, uint16_t ether_type, + const std::array& src_address, const std::array& dst_address, + uint32_t period_in_ms) { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket( + ifname_, cmd_id, ether_type, ip_packet_data, src_address, dst_address, period_in_ms); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setScanningMacOuiInternal(const std::array& /* oui */) { + // deprecated. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() { + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startPktFateMonitoring(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair> +WifiStaIface::getDebugTxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(legacy_fates, + &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +std::pair> +WifiStaIface::getDebugRxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector legacy_fates; + std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(legacy_fates, + &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +WifiStatus WifiStaIface::setMacAddressInternal(const std::array& mac) { + bool status = iface_util_.lock()->setMacAddress(ifname_, mac); + if (!status) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair> WifiStaIface::getFactoryMacAddressInternal() { + std::array mac = iface_util_.lock()->getFactoryMacAddress(ifname_); + if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; +} + +WifiStatus WifiStaIface::setScanModeInternal(bool enable) { + // OEM's need to implement this on their devices if needed. + LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported"; + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h new file mode 100644 index 0000000..c01c50b --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_sta_iface.h @@ -0,0 +1,157 @@ +/* + * 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 WIFI_STA_IFACE_H_ +#define WIFI_STA_IFACE_H_ + +#include +#include +#include + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a STA Iface instance. + */ +class WifiStaIface : public V1_6::IWifiStaIface { + public: + WifiStaIface(const std::string& ifname, + const std::weak_ptr legacy_hal, + const std::weak_ptr iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::set> getEventCallbacks(); + std::string getName(); + + // HIDL methods exposed. + Return getName(getName_cb hidl_status_cb) override; + Return getType(getType_cb hidl_status_cb) override; + Return registerEventCallback(const sp& callback, + registerEventCallback_cb hidl_status_cb) override; + Return getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) override; + Return installApfPacketFilter(uint32_t cmd_id, const hidl_vec& program, + installApfPacketFilter_cb hidl_status_cb) override; + Return readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) override; + Return getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) override; + Return getValidFrequenciesForBand(V1_0::WifiBand band, + getValidFrequenciesForBand_cb hidl_status_cb) override; + Return startBackgroundScan(uint32_t cmd_id, const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) override; + Return stopBackgroundScan(uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override; + Return enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override; + Return getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) override; + Return getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) override; + Return getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) override; + Return startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) override; + Return stopRssiMonitoring(uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override; + Return getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) override; + Return configureRoaming(const StaRoamingConfig& config, + configureRoaming_cb hidl_status_cb) override; + Return setRoamingState(StaRoamingState state, setRoamingState_cb hidl_status_cb) override; + Return enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) override; + Return startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec& ip_packet_data, uint16_t ether_type, + const hidl_array& src_address, const hidl_array& dst_address, + uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) override; + Return stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override; + Return setScanningMacOui(const hidl_array& oui, + setScanningMacOui_cb hidl_status_cb) override; + Return startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) override; + Return getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) override; + Return getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) override; + Return setMacAddress(const hidl_array& mac, + setMacAddress_cb hidl_status_cb) override; + Return getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override; + Return setScanMode(bool enable, setScanMode_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair getNameInternal(); + std::pair getTypeInternal(); + WifiStatus registerEventCallbackInternal(const sp& callback); + std::pair getCapabilitiesInternal(); + std::pair getApfPacketFilterCapabilitiesInternal(); + WifiStatus installApfPacketFilterInternal(uint32_t cmd_id, const std::vector& program); + std::pair> readApfPacketFilterDataInternal(); + std::pair getBackgroundScanCapabilitiesInternal(); + std::pair> getValidFrequenciesForBandInternal( + V1_0::WifiBand band); + WifiStatus startBackgroundScanInternal(uint32_t cmd_id, + const StaBackgroundScanParameters& params); + WifiStatus stopBackgroundScanInternal(uint32_t cmd_id); + WifiStatus enableLinkLayerStatsCollectionInternal(bool debug); + WifiStatus disableLinkLayerStatsCollectionInternal(); + std::pair getLinkLayerStatsInternal(); + std::pair getLinkLayerStatsInternal_1_3(); + std::pair getLinkLayerStatsInternal_1_5(); + std::pair getLinkLayerStatsInternal_1_6(); + WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi); + WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); + std::pair getRoamingCapabilitiesInternal(); + WifiStatus configureRoamingInternal(const StaRoamingConfig& config); + WifiStatus setRoamingStateInternal(StaRoamingState state); + WifiStatus enableNdOffloadInternal(bool enable); + WifiStatus startSendingKeepAlivePacketsInternal(uint32_t cmd_id, + const std::vector& ip_packet_data, + uint16_t ether_type, + const std::array& src_address, + const std::array& dst_address, + uint32_t period_in_ms); + WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id); + WifiStatus setScanningMacOuiInternal(const std::array& oui); + WifiStatus startDebugPacketFateMonitoringInternal(); + std::pair> getDebugTxPacketFatesInternal(); + std::pair> getDebugRxPacketFatesInternal(); + WifiStatus setMacAddressInternal(const std::array& mac); + std::pair> getFactoryMacAddressInternal(); + WifiStatus setScanModeInternal(bool enable); + + std::string ifname_; + std::weak_ptr legacy_hal_; + std::weak_ptr iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiStaIface); +}; + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STA_IFACE_H_ diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp new file mode 100644 index 0000000..3b18e53 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { + +std::string legacyErrorToString(legacy_hal::wifi_error error) { + switch (error) { + case legacy_hal::WIFI_SUCCESS: + return "SUCCESS"; + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + return "UNINITIALIZED"; + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return "NOT_AVAILABLE"; + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return "NOT_SUPPORTED"; + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + return "INVALID_ARGS"; + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return "INVALID_REQUEST_ID"; + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return "TIMED_OUT"; + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return "TOO_MANY_REQUESTS"; + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case legacy_hal::WIFI_ERROR_BUSY: + return "BUSY"; + case legacy_hal::WIFI_ERROR_UNKNOWN: + return "UNKNOWN"; + default: + return "UNKNOWN ERROR"; + } +} + +WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description) { + return {code, description}; +} + +WifiStatus createWifiStatus(WifiStatusCode code) { + return createWifiStatus(code, ""); +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, const std::string& desc) { + switch (error) { + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc); + + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc); + + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc); + + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", timed out"); + + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", too many requests"); + + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", out of memory"); + + case legacy_hal::WIFI_ERROR_BUSY: + return createWifiStatus(WifiStatusCode::ERROR_BUSY); + + case legacy_hal::WIFI_ERROR_NONE: + return createWifiStatus(WifiStatusCode::SUCCESS, desc); + + case legacy_hal::WIFI_ERROR_UNKNOWN: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown"); + + default: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown error"); + } +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { + return createWifiStatusFromLegacyError(error, ""); +} + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h new file mode 100644 index 0000000..ea1c294 --- /dev/null +++ b/wifi/wifi_legacy_service/1.0-legacy/wifi_status_util.h @@ -0,0 +1,44 @@ +/* + * 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 WIFI_STATUS_UTIL_H_ +#define WIFI_STATUS_UTIL_H_ + +#include + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_6 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +std::string legacyErrorToString(legacy_hal::wifi_error error); +WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description); +WifiStatus createWifiStatus(WifiStatusCode code); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, + const std::string& description); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error); + +} // namespace implementation +} // namespace V1_6 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STATUS_UTIL_H_ -- cgit v1.2.3