diff --git a/android/1.0/Android.mk b/android/1.0/Android.mk index 9337325f..112ae8bd 100644 --- a/android/1.0/Android.mk +++ b/android/1.0/Android.mk @@ -2,6 +2,9 @@ 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 := \ @@ -57,6 +60,9 @@ 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 diff --git a/android/1.0/Gnss.cpp b/android/1.0/Gnss.cpp index d85e0a40..4aac432f 100644 --- a/android/1.0/Gnss.cpp +++ b/android/1.0/Gnss.cpp @@ -56,6 +56,8 @@ void location_on_battery_status_changed(bool charging) { Gnss::Gnss() { ENTRY_LOG_CALLFLOW(); sGnss = this; + // initilize gnss interface at first in case needing notify battery status + sGnss->getGnssInterface()->initialize(); // register health client to listen on battery change loc_extn_battery_properties_listener_init(location_on_battery_status_changed); // clear pending GnssConfig diff --git a/android/1.0/GnssConfiguration.cpp b/android/1.0/GnssConfiguration.cpp index 0b622494..73c9d5c2 100644 --- a/android/1.0/GnssConfiguration.cpp +++ b/android/1.0/GnssConfiguration.cpp @@ -65,6 +65,9 @@ Return GnssConfiguration::setSuplVersion(uint32_t version) { config.size = sizeof(GnssConfig); config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; switch (version) { + case 0x00020004: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4; + break; case 0x00020002: config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2; break; diff --git a/android/1.0/location_api/GnssAPIClient.cpp b/android/1.0/location_api/GnssAPIClient.cpp index b9fe2b25..eb785915 100644 --- a/android/1.0/location_api/GnssAPIClient.cpp +++ b/android/1.0/location_api/GnssAPIClient.cpp @@ -174,7 +174,6 @@ bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, // 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) diff --git a/android/1.1/Android.mk b/android/1.1/Android.mk index fb72de11..132c1e1e 100644 --- a/android/1.1/Android.mk +++ b/android/1.1/Android.mk @@ -2,6 +2,9 @@ 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 := \ @@ -58,6 +61,9 @@ 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 diff --git a/android/1.1/Gnss.cpp b/android/1.1/Gnss.cpp index bea556fe..277dbc16 100644 --- a/android/1.1/Gnss.cpp +++ b/android/1.1/Gnss.cpp @@ -97,6 +97,8 @@ void location_on_battery_status_changed(bool charging) { Gnss::Gnss() { ENTRY_LOG_CALLFLOW(); sGnss = this; + // initilize gnss interface at first in case needing notify battery status + sGnss->getGnssInterface()->initialize(); // register health client to listen on battery change loc_extn_battery_properties_listener_init(location_on_battery_status_changed); // clear pending GnssConfig diff --git a/android/1.1/GnssConfiguration.cpp b/android/1.1/GnssConfiguration.cpp index 93f96457..708e2c1a 100644 --- a/android/1.1/GnssConfiguration.cpp +++ b/android/1.1/GnssConfiguration.cpp @@ -65,6 +65,9 @@ Return GnssConfiguration::setSuplVersion(uint32_t version) { config.size = sizeof(GnssConfig); config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; switch (version) { + case 0x00020004: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4; + break; case 0x00020002: config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2; break; diff --git a/android/1.1/location_api/GnssAPIClient.cpp b/android/1.1/location_api/GnssAPIClient.cpp index 9a95fdfe..be4d6596 100644 --- a/android/1.1/location_api/GnssAPIClient.cpp +++ b/android/1.1/location_api/GnssAPIClient.cpp @@ -174,7 +174,6 @@ bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, // 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) diff --git a/android/2.0/Android.mk b/android/2.0/Android.mk index 7c555042..d9ac77ca 100644 --- a/android/2.0/Android.mk +++ b/android/2.0/Android.mk @@ -2,6 +2,9 @@ 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 := \ @@ -70,6 +73,9 @@ 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 diff --git a/android/2.0/Gnss.cpp b/android/2.0/Gnss.cpp index af76b727..2276c148 100644 --- a/android/2.0/Gnss.cpp +++ b/android/2.0/Gnss.cpp @@ -96,6 +96,8 @@ void location_on_battery_status_changed(bool charging) { Gnss::Gnss() { ENTRY_LOG_CALLFLOW(); sGnss = this; + // initilize gnss interface at first in case needing notify battery status + sGnss->getGnssInterface()->initialize(); // register health client to listen on battery change loc_extn_battery_properties_listener_init(location_on_battery_status_changed); // clear pending GnssConfig diff --git a/android/2.0/GnssConfiguration.cpp b/android/2.0/GnssConfiguration.cpp index 363d2b1e..069c0365 100644 --- a/android/2.0/GnssConfiguration.cpp +++ b/android/2.0/GnssConfiguration.cpp @@ -55,6 +55,9 @@ Return GnssConfiguration::setSuplVersion(uint32_t version) { config.size = sizeof(GnssConfig); config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; switch (version) { + case 0x00020004: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_4; + break; case 0x00020002: config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2; break; diff --git a/android/2.0/android.hardware.gnss@2.0-service-qti.rc b/android/2.0/android.hardware.gnss@2.0-service-qti.rc index 36ee47c7..ad46d5d2 100644 --- a/android/2.0/android.hardware.gnss@2.0-service-qti.rc +++ b/android/2.0/android.hardware.gnss@2.0-service-qti.rc @@ -1,4 +1,4 @@ service gnss_service /vendor/bin/hw/android.hardware.gnss@2.0-service-qti class hal user gps - group system gps radio + group system gps radio vendor_qti_diag diff --git a/android/2.0/location_api/GnssAPIClient.cpp b/android/2.0/location_api/GnssAPIClient.cpp index a3cdd278..d505241c 100644 --- a/android/2.0/location_api/GnssAPIClient.cpp +++ b/android/2.0/location_api/GnssAPIClient.cpp @@ -223,7 +223,6 @@ bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, // 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) diff --git a/android/2.0/location_api/LocationUtil.cpp b/android/2.0/location_api/LocationUtil.cpp index 38a083af..8a30066f 100644 --- a/android/2.0/location_api/LocationUtil.cpp +++ b/android/2.0/location_api/LocationUtil.cpp @@ -88,10 +88,41 @@ void convertGnssLocation(Location& in, V2_0::GnssLocation& out) struct timespec sinceBootTime; struct timespec currentTime; - if (0 == clock_gettime(CLOCK_BOOTTIME,&sinceBootTime) && - 0 == clock_gettime(CLOCK_REALTIME,¤tTime)) { + 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; - int64_t sinceBootTimeNanos = sinceBootTime.tv_sec*1000000000 + sinceBootTime.tv_nsec; + /* 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 "" @@ -110,8 +141,10 @@ void convertGnssLocation(Location& in, V2_0::GnssLocation& out) __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) diff --git a/android/utils/Android.mk b/android/utils/Android.mk index 47b40811..0e4c9536 100644 --- a/android/utils/Android.mk +++ b/android/utils/Android.mk @@ -2,6 +2,9 @@ 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) @@ -23,6 +26,9 @@ LOCAL_SHARED_LIBRARIES := \ android.hardware.power@1.2 \ libbase +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + LOCAL_STATIC_LIBRARIES := libhealthhalutils LOCAL_CFLAGS += -DBATTERY_LISTENER_ENABLED diff --git a/android/utils/battery_listener.cpp b/android/utils/battery_listener.cpp index a790702b..8547e41e 100644 --- a/android/utils/battery_listener.cpp +++ b/android/utils/battery_listener.cpp @@ -31,12 +31,15 @@ #undef LOG_TAG #endif #define LOG_TAG "LocSvc_BatteryListener" +#define LOG_NDEBUG 0 #include #include #include #include #include +#include + using android::hardware::interfacesEqual; using android::hardware::Return; using android::hardware::Void; @@ -99,24 +102,25 @@ status_t BatteryListenerImpl::init() } while(tries < GET_HEALTH_SVC_RETRY_CNT); if (mHealth == NULL) { - ALOGE("no health service found, retries %d", tries); + LOC_LOGe("no health service found, retries %d", tries); return NO_INIT; } else { - ALOGI("Get health service in %d tries", tries); + LOC_LOGi("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"); + LOC_LOGe("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"); + if (!ret.isOk()) { + LOC_LOGe("batterylistener: get charge status transaction error"); + } + if (mStatus == BatteryStatus::UNKNOWN) { + LOC_LOGw("batterylistener: init: invalid battery status"); + } mDone = false; mThread = std::make_unique([this]() { std::unique_lock l(mLock); @@ -146,7 +150,7 @@ status_t BatteryListenerImpl::init() } default: bool c = statusToBool(local_status); - ALOGI("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING"); + LOC_LOGi("healthInfo cb thread: cb %s", c ? "CHARGING" : "NOT CHARGING"); l.unlock(); mCb(c); l.lock(); @@ -156,13 +160,14 @@ status_t BatteryListenerImpl::init() }); auto reg = mHealth->registerCallback(this); if (!reg.isOk()) { - ALOGE("Transaction error in registeringCb to HealthHAL death: %s", + LOC_LOGe("Transaction error in registeringCb to HealthHAL death: %s", reg.description().c_str()); } auto linked = mHealth->linkToDeath(this, 0 /* cookie */); if (!linked.isOk() || linked == false) { - ALOGE("Transaction error in linking to HealthHAL death: %s", linked.description().c_str()); + LOC_LOGe("Transaction error in linking to HealthHAL death: %s", + linked.description().c_str()); } return NO_ERROR; } @@ -181,7 +186,7 @@ BatteryListenerImpl::~BatteryListenerImpl() mHealth->unlinkToDeath(this); auto r = mHealth->unlinkToDeath(this); if (!r.isOk() || r == false) { - ALOGE("Transaction error in unregister to HealthHAL death: %s", + LOC_LOGe("Transaction error in unregister to HealthHAL death: %s", r.description().c_str()); } } @@ -195,10 +200,10 @@ void BatteryListenerImpl::serviceDied(uint64_t cookie __unused, { std::lock_guard _l(mLock); if (mHealth == NULL || !interfacesEqual(mHealth, who.promote())) { - ALOGE("health not initialized or unknown interface died"); + LOC_LOGe("health not initialized or unknown interface died"); return; } - ALOGI("health service died, reinit"); + LOC_LOGi("health service died, reinit"); mDone = true; } mThread->join(); @@ -212,9 +217,8 @@ void BatteryListenerImpl::serviceDied(uint64_t cookie __unused, // 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); + const hardware::health::V2_0::HealthInfo& info) { + LOC_LOGv("healthInfoChanged: %d", info.legacy.batteryStatus); std::unique_lock l(mLock); if (info.legacy.batteryStatus != mStatus) { mStatus = info.legacy.batteryStatus; @@ -224,29 +228,29 @@ Return BatteryListenerImpl::healthInfoChanged( } static sp batteryListener; -status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb) -{ - ALOGV("batteryPropertiesListenerInit entry"); + +bool batteryPropertiesListenerIsCharging() { + return batteryListener->isCharging(); +} + +status_t batteryPropertiesListenerInit(BatteryListenerImpl::cb_fn_t cb) { batteryListener = new BatteryListenerImpl(cb); + bool isCharging = batteryPropertiesListenerIsCharging(); + LOC_LOGv("charging status: %s charging", isCharging ? "" : "not");; + if (isCharging) { + cb(isCharging); + } return NO_ERROR; } -status_t batteryPropertiesListenerDeinit() -{ +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"); +void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) { if (!sIsBatteryListened) { std::thread t1(android::batteryPropertiesListenerInit, [=](bool charging) { fn(charging); }); @@ -255,12 +259,10 @@ void loc_extn_battery_properties_listener_init(battery_status_change_fn_t fn) } } -void loc_extn_battery_properties_listener_deinit() -{ +void loc_extn_battery_properties_listener_deinit() { android::batteryPropertiesListenerDeinit(); } -bool loc_extn_battery_properties_is_charging() -{ +bool loc_extn_battery_properties_is_charging() { return android::batteryPropertiesListenerIsCharging(); } diff --git a/batching/Android.mk b/batching/Android.mk index b08d1558..b4876cd5 100644 --- a/batching/Android.mk +++ b/batching/Android.mk @@ -6,6 +6,9 @@ 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 diff --git a/build/target_specific_features.mk b/build/target_specific_features.mk index 6093f4a8..241d67c8 100644 --- a/build/target_specific_features.mk +++ b/build/target_specific_features.mk @@ -15,8 +15,6 @@ GNSS_CFLAGS := \ -Wno-error=switch \ -Wno-error=date-time -LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow - # GPS-HIDL GNSS_HIDL_1_0_TARGET_LIST := msm8960 GNSS_HIDL_1_0_TARGET_LIST += msm8974 @@ -68,3 +66,7 @@ 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/core/Android.mk b/core/Android.mk index bd955c1f..ce5d6a8e 100644 --- a/core/Android.mk +++ b/core/Android.mk @@ -6,6 +6,9 @@ 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 diff --git a/core/ContextBase.cpp b/core/ContextBase.cpp index d5c3108f..3b8ffc6e 100644 --- a/core/ContextBase.cpp +++ b/core/ContextBase.cpp @@ -70,7 +70,8 @@ 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'}, @@ -78,13 +79,20 @@ const loc_param_s_type ContextBase::mGps_conf_table[] = {"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'}, + {"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'}, + {"NI_SUPL_DENY_ON_NFW_LOCKED", &mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED, NULL, 'n'}, }; const loc_param_s_type ContextBase::mSap_conf_table[] = @@ -171,13 +179,21 @@ void ContextBase::readConfig() /* default configuration value of constrained time uncertainty mode: feature disabled, time uncertainty threshold defined by modem, and unlimited power budget */ +#ifdef FEATURE_AUTOMOTIVE + mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 1; +#else mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 0; +#endif mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD = 0.0; mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET = 0; + /* default configuration value of position assisted clock estimator mode */ mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED = 0; /* default configuration QTI GNSS H/W */ mGps_conf.GNSS_DEPLOYMENT = 0; + mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0; + /* default configuration for NI_SUPL_DENY_ON_NFW_LOCKED */ + mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED = 0; UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table); UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table); diff --git a/core/ContextBase.h b/core/ContextBase.h index 5da76e26..e63450ff 100644 --- a/core/ContextBase.h +++ b/core/ContextBase.h @@ -74,6 +74,8 @@ typedef struct loc_gps_cfg_s char PROXY_APP_PACKAGE_NAME[LOC_MAX_PARAM_STRING]; uint32_t CP_MTLR_ES; uint32_t GNSS_DEPLOYMENT; + uint32_t CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED; + uint32_t NI_SUPL_DENY_ON_NFW_LOCKED; } loc_gps_cfg_s_type; /* NOTE: the implementaiton of the parser casts number diff --git a/core/EngineHubProxyBase.h b/core/EngineHubProxyBase.h index ec881f69..d46bca25 100644 --- a/core/EngineHubProxyBase.h +++ b/core/EngineHubProxyBase.h @@ -101,6 +101,11 @@ public: (void) additionalSystemInfo; return false; } + + inline virtual bool configLeverArm(const LeverArmConfigInfo& configInfo) { + (void) configInfo; + return false; + } }; typedef std::function @@ -113,6 +118,9 @@ typedef std::function GnssAdapterReqAidingDataCb; +typedef std::function + GnssAdapterUpdateNHzRequirementCb; + // potential parameters: message queue: MsgTask * msgTask; // callback function to report back dr and ppe position and sv report typedef EngineHubProxyBase* (getEngHubProxyFn)( @@ -120,7 +128,8 @@ typedef EngineHubProxyBase* (getEngHubProxyFn)( IOsObserver* osObserver, GnssAdapterReportEnginePositionsEventCb positionEventCb, GnssAdapterReportSvEventCb svEventCb, - GnssAdapterReqAidingDataCb reqAidingDataCb); + GnssAdapterReqAidingDataCb reqAidingDataCb, + GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb); } // namespace loc_core diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp index 1b844e57..1e91cf83 100644 --- a/core/LocAdapterBase.cpp +++ b/core/LocAdapterBase.cpp @@ -43,13 +43,20 @@ namespace loc_core { // the right locApi should get created. LocAdapterBase::LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, ContextBase* context, bool isMaster, - LocAdapterProxyBase *adapterProxyBase) : + LocAdapterProxyBase *adapterProxyBase, + bool waitForDoneInit) : mIsMaster(isMaster), mEvtMask(mask), mContext(context), mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase), mMsgTask(context->getMsgTask()), mIsEngineCapabilitiesKnown(ContextBase::sIsEngineCapabilitiesKnown) { - mLocApi->addAdapter(this); + LOC_LOGd("waitForDoneInit: %d", waitForDoneInit); + if (!waitForDoneInit) { + mLocApi->addAdapter(this); + mAdapterAdded = true; + } else { + mAdapterAdded = false; + } } uint32_t LocAdapterBase::mSessionIdCounter(1); diff --git a/core/LocAdapterBase.h b/core/LocAdapterBase.h index 909b6fea..7ca3ecda 100644 --- a/core/LocAdapterBase.h +++ b/core/LocAdapterBase.h @@ -70,9 +70,11 @@ protected: LocApiBase* mLocApi; LocAdapterProxyBase* mLocAdapterProxyBase; const MsgTask* mMsgTask; + bool mAdapterAdded; + inline LocAdapterBase(const MsgTask* msgTask) : mIsMaster(false), mEvtMask(0), mContext(NULL), mLocApi(NULL), - mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {} + mLocAdapterProxyBase(NULL), mMsgTask(msgTask), mAdapterAdded(false) {} /* ==== CLIENT ========================================================================= */ typedef std::map ClientDataMap; @@ -89,9 +91,27 @@ protected: public: inline virtual ~LocAdapterBase() { mLocApi->removeAdapter(this); } + // When waitForDoneInit is not specified or specified as false, + // handleEngineUpEvent may be called on the child adapter object from + // a different thread before the constructor of the child + // object finishes. + // + // If the handleEngineUpEvent relies on member variables of the constructor + // of the child adapter to be initialized first, we need to specify the + // waitForDoneInit to *TRUE* to delay handleEngineUpEvent to get called + // until when the child adapter finishes its initialization and notify + // LocAdapterBase via doneInit method. LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, ContextBase* context, bool isMaster = false, - LocAdapterProxyBase *adapterProxyBase = NULL); + LocAdapterProxyBase *adapterProxyBase = NULL, + bool waitForDoneInit = false); + + inline void doneInit() { + if (!mAdapterAdded) { + mLocApi->addAdapter(this); + mAdapterAdded = true; + } + } inline LOC_API_ADAPTER_EVENT_MASK_T checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const { diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index 8c79cf74..71abdf9f 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -756,24 +756,27 @@ DEFAULT_IMPL() void LocApiBase::getBlacklistSv() DEFAULT_IMPL() -void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/) +void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/, + LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() void LocApiBase::getConstellationControl() DEFAULT_IMPL() -void LocApiBase::resetConstellationControl() +void LocApiBase::resetConstellationControl(LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() -LocationError LocApiBase:: +void LocApiBase:: setConstrainedTuncMode(bool /*enabled*/, float /*tuncConstraint*/, - uint32_t /*energyBudget*/) -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) + uint32_t /*energyBudget*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() -LocationError LocApiBase:: - setPositionAssistedClockEstimatorMode(bool /*enabled*/) -DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) +void LocApiBase:: + setPositionAssistedClockEstimatorMode(bool /*enabled*/, + LocApiResponse* /*adapterResponse*/) +DEFAULT_IMPL() LocationError LocApiBase::getGnssEnergyConsumed() DEFAULT_IMPL(LOCATION_ERROR_SUCCESS) @@ -873,5 +876,7 @@ DEFAULT_IMPL() void LocApiBase::addToCallQueue(LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() +void LocApiBase::updateSystemPowerState(PowerStateType /*powerState*/) +DEFAULT_IMPL() } // namespace loc_core diff --git a/core/LocApiBase.h b/core/LocApiBase.h index 6dac585b..9c76bab2 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -260,12 +260,17 @@ public: virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config); virtual void setBlacklistSv(const GnssSvIdConfig& config); virtual void getBlacklistSv(); - virtual void setConstellationControl(const GnssSvTypeConfig& config); + virtual void setConstellationControl(const GnssSvTypeConfig& config, + LocApiResponse *adapterResponse=nullptr); virtual void getConstellationControl(); - virtual void resetConstellationControl(); - virtual LocationError setConstrainedTuncMode(bool enabled, float tuncConstraint, - uint32_t energyBudget); - virtual LocationError setPositionAssistedClockEstimatorMode(bool enabled); + virtual void resetConstellationControl(LocApiResponse *adapterResponse=nullptr); + + virtual void setConstrainedTuncMode(bool enabled, + float tuncConstraint, + uint32_t energyBudget, + LocApiResponse* adapterResponse=nullptr); + virtual void setPositionAssistedClockEstimatorMode(bool enabled, + LocApiResponse* adapterResponse=nullptr); virtual LocationError getGnssEnergyConsumed(); virtual void addGeofence(uint32_t clientId, const GeofenceOption& options, @@ -312,6 +317,7 @@ public: void updateEvtMask(); void updateNmeaMask(uint32_t mask); + virtual void updateSystemPowerState(PowerStateType systemPowerState); }; typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, diff --git a/core/Makefile.am b/core/Makefile.am index ffd93579..1199a523 100644 --- a/core/Makefile.am +++ b/core/Makefile.am @@ -56,6 +56,10 @@ libloc_core_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 libloc_core_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) endif +if USE_FEATURE_AUTOMOTIVE +AM_CFLAGS += -DFEATURE_AUTOMOTIVE +endif + libloc_core_la_LIBADD = -ldl $(GPSUTILS_LIBS) #Create and Install libraries diff --git a/core/SystemStatus.cpp b/core/SystemStatus.cpp index 0624580b..393eead1 100644 --- a/core/SystemStatus.cpp +++ b/core/SystemStatus.cpp @@ -1346,6 +1346,9 @@ SystemStatus::SystemStatus(const MsgTask* msgTask) : template bool SystemStatus::setIteminReport(TYPE_REPORT& report, TYPE_ITEM&& s) { + if (s.ignore()) { + return false; + } if (!report.empty() && report.back().equals(static_cast(s.collate(report.back())))) { // there is no change - just update reported timestamp report.back().mUtcReported = s.mUtcReported; diff --git a/core/SystemStatus.h b/core/SystemStatus.h index 2cfb25dc..8ec85fae 100644 --- a/core/SystemStatus.h +++ b/core/SystemStatus.h @@ -87,6 +87,7 @@ public: return *this; } virtual void dump(void) {}; + inline virtual bool ignore() { return false; }; }; class SystemStatusLocation : public SystemStatusItemBase @@ -103,7 +104,7 @@ public: mLocation(location), mLocationEx(locationEx) {} bool equals(const SystemStatusLocation& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWM1; @@ -133,7 +134,7 @@ public: mTimeUncNs(0ULL) {} inline SystemStatusTimeAndClock(const SystemStatusPQWM1& nmea); bool equals(const SystemStatusTimeAndClock& peer); - void dump(void); + void dump(void) override; }; class SystemStatusXoState : public SystemStatusItemBase @@ -144,7 +145,7 @@ public: mXoState(0) {} inline SystemStatusXoState(const SystemStatusPQWM1& nmea); bool equals(const SystemStatusXoState& peer); - void dump(void); + void dump(void) override; }; class SystemStatusRfAndParams : public SystemStatusItemBase @@ -191,7 +192,7 @@ public: mGalBpAmpQ(0) {} inline SystemStatusRfAndParams(const SystemStatusPQWM1& nmea); bool equals(const SystemStatusRfAndParams& peer); - void dump(void); + void dump(void) override; }; class SystemStatusErrRecovery : public SystemStatusItemBase @@ -202,7 +203,8 @@ public: mRecErrorRecovery(0) {}; inline SystemStatusErrRecovery(const SystemStatusPQWM1& nmea); bool equals(const SystemStatusErrRecovery& peer); - void dump(void); + inline bool ignore() override { return 0 == mRecErrorRecovery; }; + void dump(void) override; }; class SystemStatusPQWP1; @@ -226,7 +228,7 @@ public: mEpiSrc(0) {} inline SystemStatusInjectedPosition(const SystemStatusPQWP1& nmea); bool equals(const SystemStatusInjectedPosition& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP2; @@ -248,7 +250,7 @@ public: mBestAltUnc(0) {} inline SystemStatusBestPosition(const SystemStatusPQWP2& nmea); bool equals(const SystemStatusBestPosition& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP3; @@ -284,7 +286,7 @@ public: mNavicXtraValid(0) {} inline SystemStatusXtra(const SystemStatusPQWP3& nmea); bool equals(const SystemStatusXtra& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP4; @@ -304,7 +306,7 @@ public: mQzssEpheValid(0) {} inline SystemStatusEphemeris(const SystemStatusPQWP4& nmea); bool equals(const SystemStatusEphemeris& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP5; @@ -350,7 +352,7 @@ public: mNavicBadMask(0) {} inline SystemStatusSvHealth(const SystemStatusPQWP5& nmea); bool equals(const SystemStatusSvHealth& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP6; @@ -362,7 +364,7 @@ public: mFixInfoMask(0) {} inline SystemStatusPdr(const SystemStatusPQWP6& nmea); bool equals(const SystemStatusPdr& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWP7; @@ -386,7 +388,7 @@ public: } inline SystemStatusNavData(const SystemStatusPQWP7& nmea); bool equals(const SystemStatusNavData& peer); - void dump(void); + void dump(void) override; }; class SystemStatusPQWS1; @@ -400,7 +402,7 @@ public: mHepeLimit(0) {} inline SystemStatusPositionFailure(const SystemStatusPQWS1& nmea); bool equals(const SystemStatusPositionFailure& peer); - void dump(void); + void dump(void) override; }; /****************************************************************************** @@ -759,7 +761,7 @@ public: inline bool equals(const SystemStatusTac& peer) { return (mValue == peer.mValue); } - inline void dump(void) { + inline void dump(void) override { LOC_LOGD("Tac: value=%s", mValue.c_str()); } }; @@ -775,7 +777,7 @@ public: inline bool equals(const SystemStatusMccMnc& peer) { return (mValue == peer.mValue); } - inline void dump(void) { + inline void dump(void) override { LOC_LOGD("TacMccMnc value=%s", mValue.c_str()); } }; diff --git a/core/configure.ac b/core/configure.ac index c3e062b6..548c5e59 100644 --- a/core/configure.ac +++ b/core/configure.ac @@ -74,6 +74,18 @@ fi AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") +AC_ARG_WITH([auto_feature], + AC_HELP_STRING([--with-auto_feature=@<:@dir@:>@], + [Using Automotive feature]), + [], + with_auto_feature=no) + +if test "x$with_auto_feature" != "xno"; then + CPPFLAGS="${CPPFLAGS} -DFEATURE_AUTOMOTIVE" +fi + +AM_CONDITIONAL(USE_FEATURE_AUTOMOTIVE, test "x${with_auto_feature}" = "xyes") + AC_CONFIG_FILES([ \ Makefile \ loc-core.pc \ diff --git a/etc/gps.conf b/etc/gps.conf index 63547653..47aa8efb 100644 --- a/etc/gps.conf +++ b/etc/gps.conf @@ -99,6 +99,31 @@ DATUM_TYPE = 0 ################################ # NMEA provider (1=Modem Processor, 0=Application Processor) NMEA_PROVIDER=0 + +# Customized NMEA GGA fix quality that can be used to tell +# whether SENSOR contributed to the fix. +# +# When this configuration item is not enabled (set to any value that is not 1), +# GGA fix quality conforms to NMEA standard spec as below: +# PPP/DGNSS/SBAS correction fix w/ or w/o sensor: 2 +# RTK fixed fix w/ or w/o sensor: 4 +# RTK float fix w/ or w/o sensor: 5 +# SPE fix w/ or w/o sensor: 1 +# Sensor dead reckoning fix: 6 +# +# When this configuration is enabled (set to 1), GGA fix quality +# will be output as below: +# PPP fix w/o sensor: 59, w/ sensor: 69 +# DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62 +# RTK fixed fix w/o sensor: 4, w/ sensor: 64 +# RTK float fix w/o sensor: 5, w/ sensor: 65, +# SPE fix w/o sensor: 1, and w/ sensor: 61 +# Sensor dead reckoning fix: 6 +# +# any value that is not 1 - disabled +# 1 - enabled +CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0 + # Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE) SGLTE_TARGET=0 diff --git a/geofence/Android.mk b/geofence/Android.mk index 6e9e8706..7e0e34e8 100644 --- a/geofence/Android.mk +++ b/geofence/Android.mk @@ -6,6 +6,9 @@ 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 diff --git a/gnss/Android.mk b/gnss/Android.mk index d809bc2a..c1b5944a 100644 --- a/gnss/Android.mk +++ b/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/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index c2e4a091..5ce7b18a 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -45,7 +45,6 @@ #include #include #include - #include #define RAD2DEG (180.0 / M_PI) @@ -65,11 +64,14 @@ static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userD GnssAdapter::GnssAdapter() : LocAdapterBase(0, LocContext::getLocContext(NULL, - NULL, - LocContext::mLocationHalName, - false), true, nullptr), + NULL, + LocContext::mLocationHalName, + false), + true, nullptr, true), mEngHubProxy(new EngineHubProxyBase()), mLocPositionMode(), + mNHzNeeded(false), + mSPEAlreadyRunningAtHighestInterval(false), mGnssSvIdUsedInPosition(), mGnssSvIdUsedInPosAvail(false), mControlCallbacks(), @@ -78,6 +80,7 @@ GnssAdapter::GnssAdapter() : mGnssSvIdConfig(), mGnssSvTypeConfig(), mGnssSvTypeConfigCb(nullptr), + mLocConfigInfo{}, mNiData(), mAgpsManager(), mOdcpiRequestCb(nullptr), @@ -97,7 +100,8 @@ GnssAdapter::GnssAdapter() : mIsE911Session(NULL), mGnssMbSvIdUsedInPosition{}, mGnssMbSvIdUsedInPosAvail(false), - mSupportNfwControl(true) + mSupportNfwControl(true), + mSystemPowerState(POWER_STATE_UNKNOWN) { LOC_LOGD("%s]: Constructor %p", __func__, this); mLocPositionMode.mode = LOC_POSITION_MODE_INVALID; @@ -127,6 +131,10 @@ GnssAdapter::GnssAdapter() : readConfigCommand(); initDefaultAgpsCommand(); initEngHubProxyCommand(); + + // at last step, let us inform adapater base that we are done + // with initialization, e.g.: ready to process handleEngineUpEvent + doneInit(); } void @@ -168,6 +176,30 @@ GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOpti out.timeBetweenMeasurements = trackingOptions.tbm; } +bool +GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) { + // first check if NHz meas is needed at all, if not, just return false + // if a NHz capable engine is subscribed for NHz measurement or NHz positions, + // always run the SPE only session at 100ms TBF. + // If SPE session is already set to highest interval, no need to start it again. + + bool isSPERunningAtHighestInterval = false; + + if (!mNHzNeeded) { + LOC_LOGd("No nHz session needed."); + } else if (mSPEAlreadyRunningAtHighestInterval) { + LOC_LOGd("SPE is already running at highest interval."); + isSPERunningAtHighestInterval = true; + } else if (out.minInterval > MIN_TRACKING_INTERVAL) { + out.minInterval = MIN_TRACKING_INTERVAL; + LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF."); + mSPEAlreadyRunningAtHighestInterval = true; + } + + return isSPERunningAtHighestInterval; +} + + void GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation, const GpsLocationExtended& locationExtended, @@ -502,6 +534,8 @@ inline uint32_t GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) { switch (suplVersion) { + case GNSS_CONFIG_SUPL_VERSION_2_0_4: + return 0x00020004; case GNSS_CONFIG_SUPL_VERSION_2_0_0: return 0x00020000; case GNSS_CONFIG_SUPL_VERSION_2_0_2: @@ -795,12 +829,32 @@ GnssAdapter::setConfig() mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK); + // load tunc configuration from config file on first boot-up, + // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false + if (mLocConfigInfo.tuncConfigInfo.isValid == false) { + mLocConfigInfo.tuncConfigInfo.isValid = true; + mLocConfigInfo.tuncConfigInfo.enable = + (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1); + mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = + (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD; + mLocConfigInfo.tuncConfigInfo.energyBudget = + gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET; + } + mLocApi->setConstrainedTuncMode( - gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1, - (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD, - gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET); + mLocConfigInfo.tuncConfigInfo.enable, + mLocConfigInfo.tuncConfigInfo.tuncThresholdMs, + mLocConfigInfo.tuncConfigInfo.energyBudget); + + // load pace configuration from config file on first boot-up, + // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false + if (mLocConfigInfo.paceConfigInfo.isValid == false) { + mLocConfigInfo.paceConfigInfo.isValid = true; + mLocConfigInfo.paceConfigInfo.enable = + (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1); + } mLocApi->setPositionAssistedClockEstimatorMode( - gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED == 1); + mLocConfigInfo.paceConfigInfo.enable); if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID || sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID || @@ -1488,7 +1542,7 @@ GnssAdapter::convertToGnssSvIdConfig( LOC_LOGe("Invalid sv id %d for sv type %d", source.svId, source.constellation); } else { - *svMaskPtr |= (1 << (source.svId - initialSvId)); + *svMaskPtr |= (1ULL << (source.svId - initialSvId)); } } } @@ -1992,6 +2046,35 @@ GnssAdapter::blockCPICommand(double latitude, double longitude, sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo)); } +void +GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) { + if (POWER_STATE_UNKNOWN != systemPowerState) { + mSystemPowerState = systemPowerState; + mLocApi->updateSystemPowerState(mSystemPowerState); + } +} + +void +GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) { + LOC_LOGd("power event %d", systemPowerState); + + struct MsgUpdatePowerState : public LocMsg { + GnssAdapter& mAdapter; + PowerStateType mSystemPowerState; + + inline MsgUpdatePowerState(GnssAdapter& adapter, + PowerStateType systemPowerState) : + LocMsg(), + mAdapter(adapter), + mSystemPowerState(systemPowerState) {} + inline virtual void proc() const { + mAdapter.updateSystemPowerState(mSystemPowerState); + } + }; + + sendMsg(new MsgUpdatePowerState(*this, systemPowerState)); +} + void GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks) { @@ -2056,7 +2139,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 || it->second.gnssLocationInfoCb != nullptr) { + if (it->second.trackingCb != nullptr || + it->second.gnssLocationInfoCb != nullptr || + it->second.engineLocationsInfoCb != nullptr) { mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT; } if (it->second.gnssSvCb != nullptr) { @@ -2084,13 +2169,16 @@ GnssAdapter::updateClientsEventMask() 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; + // Nhz measurement bit is set based on callback from loc eng hub + // for Nhz engines. + mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT); + LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "", mask); } @@ -2128,9 +2216,10 @@ GnssAdapter::handleEngineUpEvent() mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); // must be called only after capabilities are known mAdapter.setConfig(); - mAdapter.restartSessions(); mAdapter.gnssSvIdConfigUpdate(); mAdapter.gnssSvTypeConfigUpdate(); + mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState()); + mAdapter.restartSessions(); for (auto msg: mAdapter.mPendingMsgs) { mAdapter.sendMsg(msg); } @@ -2150,13 +2239,31 @@ GnssAdapter::restartSessions() // odcpi session is no longer active after restart mOdcpiRequestActive = false; + // SPE will be restarted now, so set this variable to false. + mSPEAlreadyRunningAtHighestInterval = false; + + checkAndRestartTimeBasedSession(); + + for (auto it = mDistanceBasedTrackingSessions.begin(); + it != mDistanceBasedTrackingSessions.end(); ++it) { + mLocApi->startDistanceBasedTracking(it->first.id, it->second, + new LocApiResponse(*getContext(), + [] (LocationError /*err*/) {})); + } +} + +void GnssAdapter::checkAndRestartTimeBasedSession() +{ + LOC_LOGD("%s]: ", __func__); + if (!mTimeBasedTrackingSessions.empty()) { // get the LocationOptions that has the smallest interval, which should be the active one TrackingOptions smallestIntervalOptions; // size is zero until set for the first time TrackingOptions highestPowerTrackingOptions; memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions)); memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions)); - for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) { + 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) { @@ -2172,14 +2279,10 @@ GnssAdapter::restartSessions() } highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions); - mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr); - } - - for (auto it = mDistanceBasedTrackingSessions.begin(); - it != mDistanceBasedTrackingSessions.end(); ++it) { - mLocApi->startDistanceBasedTracking(it->first.id, it->second, - new LocApiResponse(*getContext(), - [] (LocationError /*err*/) {})); + // want to run SPE session at a fixed min interval in some automotive scenarios + if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) { + mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr); + } } } @@ -2212,13 +2315,6 @@ GnssAdapter::notifyClientOfCachedLocationSystemInfo( } } -bool -GnssAdapter::hasTrackingCallback(LocationAPI* client) -{ - auto it = mClientData.find(client); - return (it != mClientData.end() && (it->second.trackingCb || it->second.gnssLocationInfoCb)); -} - bool GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId) { @@ -2234,10 +2330,21 @@ GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessio } bool -GnssAdapter::hasMeasurementsCallback(LocationAPI* client) +GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client) { + bool allowed = false; auto it = mClientData.find(client); - return (it != mClientData.end() && it->second.gnssMeasurementsCb); + if (it != mClientData.end()) { + if (it->second.trackingCb || it->second.gnssLocationInfoCb || + it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb) { + allowed = true; + } else { + LOC_LOGi("missing right callback to start tracking") + } + } else { + LOC_LOGi("client %p not found", client) + } + return allowed; } bool @@ -2405,8 +2512,7 @@ GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options) return; } LocationError err = LOCATION_ERROR_SUCCESS; - if (!mAdapter.hasTrackingCallback(mClient) && - !mAdapter.hasMeasurementsCallback(mClient)) { + if (!mAdapter.hasCallbacksToStartTracking(mClient)) { err = LOCATION_ERROR_CALLBACK_MISSING; } else if (0 == mOptions.size) { err = LOCATION_ERROR_INVALID_PARAMETER; @@ -2486,6 +2592,7 @@ GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessi multiplexedOptions.minInterval = options.minInterval; updateOptions = true; } + // if session we are starting has smaller powerMode then next smallest if (options.powerMode < multiplexedPowerMode) { multiplexedOptions.powerMode = options.powerMode; @@ -2519,15 +2626,24 @@ GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId, mEngHubProxy->gnssSetFixMode(locPosMode); mEngHubProxy->gnssStartFix(); - mLocApi->startTimeBasedTracking(trackingOptions, new LocApiResponse(*getContext(), - [this, client, sessionId] (LocationError err) { - if (LOCATION_ERROR_SUCCESS != err) { - eraseTrackingSession(client, sessionId); - } + // want to run SPE session at a fixed min interval in some automotive scenarios + // use a local copy of TrackingOptions as the TBF may get modified in the + // checkAndSetSPEToRunforNHz function + TrackingOptions tempOptions(trackingOptions); + if (!checkAndSetSPEToRunforNHz(tempOptions)) { + mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(), + [this, client, sessionId] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + eraseTrackingSession(client, sessionId); + } + + reportResponse(client, err, sessionId); + } + )); + } else { + reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId); + } - reportResponse(client, err, sessionId); - } - )); } void @@ -2541,16 +2657,23 @@ GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId, 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); + // want to run SPE session at a fixed min interval in some automotive scenarios + // use a local copy of TrackingOptions as the TBF may get modified in the + // checkAndSetSPEToRunforNHz function + TrackingOptions tempOptions(updatedOptions); + if(!checkAndSetSPEToRunforNHz(tempOptions)) { + mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(), + [this, client, sessionId, oldOptions] (LocationError err) { + if (LOCATION_ERROR_SUCCESS != err) { + // restore the old LocationOptions + saveTrackingSession(client, sessionId, oldOptions); + } + reportResponse(client, err, sessionId); } - - reportResponse(client, err, sessionId); - } - )); + )); + } else { + reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId); + } } void @@ -2851,6 +2974,8 @@ GnssAdapter::stopTracking(LocationAPI* client, uint32_t id) [this, client, id] (LocationError err) { reportResponse(client, err, id); })); + + mSPEAlreadyRunningAtHighestInterval = false; } bool @@ -3071,21 +3196,35 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, int msInWeek) { // 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 + // also, send out SPE fix promptly to the clients that have registered + // with SPE report + LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d", + locationExtended.locOutputEngType, ulpLocation.unpropagatedPosition, + status); if (true == initEngHubProxy()){ + // send the SPE fix to engine hub mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status); + // report out all SPE fix if it is not propagated, even for failed fix + if (false == ulpLocation.unpropagatedPosition) { + EngineLocationInfo engLocationInfo = {}; + engLocationInfo.location = ulpLocation; + engLocationInfo.locationExtended = locationExtended; + engLocationInfo.sessionStatus = status; + reportEnginePositionsEvent(1, &engLocationInfo); + } return; } + // unpropagated report: is only for engine hub to consume and no need + // to send out to the clients 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 + // Fix is from QMI, and it is not an unpropagated position and engine hub + // is not loaded, queue the message when message is processed, the position + // can be dispatched to requesting client that registers for SPE report struct MsgReportPosition : public LocMsg { GnssAdapter& mAdapter; const UlpLocation mUlpLocation; @@ -3255,10 +3394,11 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, } } - // 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)) { + // if PACE is enabled and engine hub is running and the fix is from sensor, + // e.g.: DRE, inject DRE fix to modem + if ((true == mLocConfigInfo.paceConfigInfo.isValid && + true == mLocConfigInfo.paceConfigInfo.enable) && + (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) { mLocApi->injectPosition(locationInfo, false); } } @@ -3272,9 +3412,10 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, (0 == ulpLocation.gpsLocation.longitude) && (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability)); uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix); + bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED); std::vector nmeaArraystr; loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, - generate_nmea, nmeaArraystr); + generate_nmea, custom_nmea_gga, nmeaArraystr); stringstream ss; for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { ss << *itor; @@ -3484,7 +3625,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; } } @@ -3675,6 +3816,15 @@ GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* else { mAdapter.requestNiNotify(mNotify, mData, false); } + } else if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) && + GNSS_NI_TYPE_SUPL == mNotify.type && !bIsInEmergency && + !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) && + (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) && + 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) { + // If 'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked + // If an NI SUPL Request that does not have Privacy Override option comes when + // NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1, then deny it + mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData); } else { mAdapter.requestNiNotify(mNotify, mData, false); } @@ -4930,6 +5080,263 @@ GnssAdapter::nfwControlCommand(bool enable) { } } +// Set tunc constrained mode, use 0 session id to indicate +// that no callback is needed. Session id 0 is used for calls that +// are not invoked from the integration api, e.g.: initial configuration +// from the configure file +void +GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint, + uint32_t energyBudget, uint32_t sessionId) { + + mLocConfigInfo.tuncConfigInfo.isValid = true; + mLocConfigInfo.tuncConfigInfo.enable = enable; + mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint; + mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget; + + LocApiResponse* locApiResponse = nullptr; + if (sessionId != 0) { + locApiResponse = + new LocApiResponse(*getContext(), + [this, sessionId] (LocationError err) { + reportResponse(err, sessionId);}); + if (!locApiResponse) { + LOC_LOGe("memory alloc failed"); + } + } + mLocApi->setConstrainedTuncMode( + enable, tuncConstraint, energyBudget, locApiResponse); +} + +uint32_t +GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint, + uint32_t energyBudget) { + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGd("session id %u", sessionId); + + struct MsgEnableTUNC : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + bool mEnable; + float mTuncConstraint; + uint32_t mEnergyBudget; + + inline MsgEnableTUNC(GnssAdapter& adapter, + uint32_t sessionId, + bool enable, + float tuncConstraint, + uint32_t energyBudget) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId), + mEnable(enable), + mTuncConstraint(tuncConstraint), + mEnergyBudget(energyBudget) {} + inline virtual void proc() const { + mAdapter.setConstrainedTunc(mEnable, mTuncConstraint, + mEnergyBudget, mSessionId); + } + }; + + sendMsg(new MsgEnableTUNC(*this, sessionId, enable, + tuncConstraint, energyBudget)); + + return sessionId; +} + +// Set position assisted clock estimator, use 0 session id to indicate +// that no callback is needed. Session id 0 is used for calls that are +// not invoked from the integration api, e.g.: initial configuration +// from the configure file. +void +GnssAdapter::setPositionAssistedClockEstimator(bool enable, + uint32_t sessionId) { + + mLocConfigInfo.paceConfigInfo.isValid = true; + mLocConfigInfo.paceConfigInfo.enable = enable; + LocApiResponse* locApiResponse = nullptr; + if (sessionId != 0) { + locApiResponse = + new LocApiResponse(*getContext(), + [this, sessionId] (LocationError err) { + reportResponse(err, sessionId);}); + if (!locApiResponse) { + LOC_LOGe("memory alloc failed"); + } + } + mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse); +} + +uint32_t +GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) { + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGd("session id %u", sessionId); + + struct MsgEnablePACE : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + bool mEnable; + inline MsgEnablePACE(GnssAdapter& adapter, + uint32_t sessionId, bool enable) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId), + mEnable(enable){} + inline virtual void proc() const { + mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId); + } + }; + + sendMsg(new MsgEnablePACE(*this, sessionId, enable)); + return sessionId; +} + +void +GnssAdapter::updateSvConfig(uint32_t sessionId, + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) { + + // check whether if any constellation is removed from the new config + GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask & + (mGnssSvTypeConfig.enabledSvTypesMask ^ svTypeConfig.enabledSvTypesMask); + // Send reset if any constellation is removed from the enabled list + if (enabledRemoved != 0) { + mLocApi->resetConstellationControl(); + } + + mGnssSvTypeConfig = svTypeConfig; + mGnssSvIdConfig = svIdConfig; + + // Send blacklist info + mLocApi->setBlacklistSv(mGnssSvIdConfig); + + // Send only enabled constellation config + GnssSvTypeConfig svTypeConfigCopy = {sizeof(GnssSvTypeConfig), 0, 0}; + svTypeConfigCopy.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask; + LocApiResponse* locApiResponse = new LocApiResponse(*getContext(), + [this, sessionId] (LocationError err) { + reportResponse(err, sessionId);}); + if (!locApiResponse) { + LOC_LOGe("memory alloc failed"); + } + mLocApi->setConstellationControl(svTypeConfigCopy, locApiResponse); +} + +uint32_t GnssAdapter::gnssUpdateSvConfigCommand( + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) { + + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGd("session id %u", sessionId); + + struct MsgUpdateSvConfig : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + GnssSvTypeConfig mSvTypeConfig; + GnssSvIdConfig mSvIdConfig; + + inline MsgUpdateSvConfig(GnssAdapter& adapter, + uint32_t sessionId, + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId), + mSvTypeConfig(svTypeConfig), + mSvIdConfig(svIdConfig) {} + inline virtual void proc() const { + mAdapter.updateSvConfig(mSessionId, mSvTypeConfig, mSvIdConfig); + } + }; + + if (sessionId != 0) { + sendMsg(new MsgUpdateSvConfig(*this, sessionId, + svTypeConfig, svIdConfig)); + } + return sessionId; +} + +void +GnssAdapter::resetSvConfig(uint32_t sessionId) { + + LocApiResponse* locApiResponse = nullptr; + if (sessionId != 0) { + locApiResponse = + new LocApiResponse(*getContext(), + [this, sessionId] (LocationError err) { + reportResponse(err, sessionId);}); + if (!locApiResponse) { + LOC_LOGe("memory alloc failed"); + } + } + mLocApi->resetConstellationControl(locApiResponse); +} + +uint32_t GnssAdapter::gnssResetSvConfigCommand() { + + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGd("session id %u", sessionId); + + struct MsgResetSvConfig : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + + inline MsgResetSvConfig(GnssAdapter& adapter, + uint32_t sessionId) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId) {} + inline virtual void proc() const { + mAdapter.resetSvConfig(mSessionId); + } + }; + + sendMsg(new MsgResetSvConfig(*this, sessionId)); + return sessionId; +} + +void +GnssAdapter::configLeverArm(uint32_t sessionId, + const LeverArmConfigInfo& configInfo) { + + LocationError err = LOCATION_ERROR_NOT_SUPPORTED; + if (true == mEngHubProxy->configLeverArm(configInfo)) { + err = LOCATION_ERROR_SUCCESS; + } + reportResponse(err, sessionId); +} + +uint32_t +GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) { + + // generated session id will be none-zero + uint32_t sessionId = generateSessionId(); + LOC_LOGd("session id %u", sessionId); + + struct MsgConfigLeverArm : public LocMsg { + GnssAdapter& mAdapter; + uint32_t mSessionId; + LeverArmConfigInfo mConfigInfo; + + inline MsgConfigLeverArm(GnssAdapter& adapter, + uint32_t sessionId, + const LeverArmConfigInfo& configInfo) : + LocMsg(), + mAdapter(adapter), + mSessionId(sessionId), + mConfigInfo(configInfo) {} + inline virtual void proc() const { + mAdapter.configLeverArm(mSessionId, mConfigInfo); + } + }; + + sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo)); + return sessionId; +} + /* ==== Eng Hub Proxy ================================================================= */ /* ======== UTILITIES ================================================================= */ void @@ -5017,11 +5424,30 @@ GnssAdapter::initEngHubProxy() { mLocApi->requestForAidingData(svDataMask); }; + GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb = + [this] (bool nHzNeeded, bool nHzMeasNeeded) { + + if (nHzMeasNeeded && + (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) { + updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT, + LOC_REGISTRATION_MASK_ENABLED); + } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) { + updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT, + LOC_REGISTRATION_MASK_DISABLED); + } + + if (mNHzNeeded != nHzNeeded) { + mNHzNeeded = nHzNeeded; + checkAndRestartTimeBasedSession(); + } + }; + getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy"); if(getter != nullptr) { EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(), reportPositionEventCb, - reportSvEventCb, reqAidingDataCb); + reportSvEventCb, reqAidingDataCb, + updateNHzRequirementCb); if (hubProxy != nullptr) { mEngHubProxy = hubProxy; engHubLoadSuccessful = true; diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index 3ccdd96d..ff8131ff 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -122,6 +122,23 @@ typedef struct { double latLonDiffThreshold; } BlockCPIInfo; +typedef struct { + bool isValid; + bool enable; + float tuncThresholdMs; // need to be specified if enable is true + uint32_t energyBudget; // need to be specified if enable is true +} TuncConfigInfo; + +typedef struct { + bool isValid; + bool enable; +} PaceConfigInfo; + +typedef struct { + TuncConfigInfo tuncConfigInfo; + PaceConfigInfo paceConfigInfo; +} LocIntegrationConfigInfo; + using namespace loc_core; namespace loc_core { @@ -138,6 +155,8 @@ class GnssAdapter : public LocAdapterBase { /* ==== Engine Hub ===================================================================== */ EngineHubProxyBase* mEngHubProxy; + bool mNHzNeeded; + bool mSPEAlreadyRunningAtHighestInterval; /* ==== TRACKING ======================================================================= */ TrackingOptionsMap mTimeBasedTrackingSessions; @@ -156,6 +175,7 @@ class GnssAdapter : public LocAdapterBase { GnssSvTypeConfig mGnssSvTypeConfig; GnssSvTypeConfigCallback mGnssSvTypeConfigCb; bool mSupportNfwControl; + LocIntegrationConfigInfo mLocConfigInfo; /* ==== NI ============================================================================= */ NiData mNiData; @@ -187,6 +207,7 @@ class GnssAdapter : public LocAdapterBase { XtraSystemStatusObserver mXtraObserver; LocationSystemInfo mLocSystemInfo; std::vector mBlacklistedSvIds; + PowerStateType mSystemPowerState; /* === Misc ===================================================================== */ BlockCPIInfo mBlockCPIInfo; @@ -228,6 +249,7 @@ public: virtual void handleEngineUpEvent(); /* ======== UTILITIES ================================================================== */ void restartSessions(); + void checkAndRestartTimeBasedSession(); /* ==== CLIENT ========================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -243,10 +265,9 @@ public: /* ======== 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 hasCallbacksToStartTracking(LocationAPI* client); bool isTrackingSession(LocationAPI* client, uint32_t sessionId); void saveTrackingSession(LocationAPI* client, uint32_t sessionId, const TrackingOptions& trackingOptions); @@ -265,6 +286,15 @@ public: const TrackingOptions& trackingOptions); void updateTracking(LocationAPI* client, uint32_t sessionId, const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions); + bool checkAndSetSPEToRunforNHz(TrackingOptions & out); + + void setConstrainedTunc(bool enable, float tuncConstraint, + uint32_t energyBudget, uint32_t sessionId); + void setPositionAssistedClockEstimator(bool enable, uint32_t sessionId); + void updateSvConfig(uint32_t sessionId, const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig); + void resetSvConfig(uint32_t sessionId); + void configLeverArm(uint32_t sessionId, const LeverArmConfigInfo& configInfo); /* ==== NI ============================================================================= */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -325,6 +355,13 @@ public: void dataConnFailedCommand(AGpsExtType agpsType); void getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb); void nfwControlCommand(bool enable); + uint32_t setConstrainedTuncCommand (bool enable, float tuncConstraint, + uint32_t energyBudget); + uint32_t setPositionAssistedClockEstimatorCommand (bool enable); + uint32_t gnssUpdateSvConfigCommand(const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig); + uint32_t gnssResetSvConfigCommand(); + uint32_t configLeverArmCommand(const LeverArmConfigInfo& configInfo); /* ========= ODCPI ===================================================================== */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */ @@ -413,6 +450,8 @@ public: return false; } + void updateSystemPowerState(PowerStateType systemPowerState); + /*======== GNSSDEBUG ================================================================*/ bool getDebugReport(GnssDebugReport& report); /* get AGC information from system status and fill it */ @@ -459,11 +498,14 @@ public: void reportPowerStateIfChanged(); void savePowerStateCallback(powerStateCallback powerStateCb){ mPowerStateCb = powerStateCb; } bool getPowerState() { return mPowerOn; } + inline PowerStateType getSystemPowerState() { return mSystemPowerState; } + void setAllowFlpNetworkFixes(uint32_t allow) { mAllowFlpNetworkFixes = allow; } uint32_t getAllowFlpNetworkFixes() { return mAllowFlpNetworkFixes; } void setSuplHostServer(const char* server, int port, LocServerType type); void notifyClientOfCachedLocationSystemInfo(LocationAPI* client, const LocationCallbacks& callbacks); + void updateSystemPowerStateCommand(PowerStateType systemPowerState); }; #endif //GNSS_ADAPTER_H diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index 76839b62..97e99e42 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -79,6 +79,14 @@ static void odcpiInject(const Location& location); static void blockCPI(double latitude, double longitude, float accuracy, int blockDurationMsec, double latLonDiffThreshold); static void updateBatteryStatus(bool charging); +static void updateSystemPowerState(PowerStateType systemPowerState); +static uint32_t setConstrainedTunc (bool enable, float tuncConstraint, + uint32_t energyBudget); +static uint32_t setPositionAssistedClockEstimator(bool enable); +static uint32_t gnssUpdateSvConfig(const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig); +static uint32_t gnssResetSvConfig(); +static uint32_t configLeverArm(const LeverArmConfigInfo& configInfo); static const GnssInterface gGnssInterface = { sizeof(GnssInterface), @@ -117,7 +125,13 @@ static const GnssInterface gGnssInterface = { nfwInit, getPowerStateChanges, injectLocationExt, - updateBatteryStatus + updateBatteryStatus, + updateSystemPowerState, + setConstrainedTunc, + setPositionAssistedClockEstimator, + gnssUpdateSvConfig, + gnssResetSvConfig, + configLeverArm, }; #ifndef DEBUG_X86 @@ -390,3 +404,52 @@ static void updateBatteryStatus(bool charging) { gGnssAdapter->getSystemStatus()->updatePowerConnectState(charging); } } + +static void updateSystemPowerState(PowerStateType systemPowerState) { + if (NULL != gGnssAdapter) { + gGnssAdapter->updateSystemPowerStateCommand(systemPowerState); + } +} + +static uint32_t setConstrainedTunc (bool enable, float tuncConstraint, uint32_t energyBudget) { + if (NULL != gGnssAdapter) { + return gGnssAdapter->setConstrainedTuncCommand(enable, tuncConstraint, energyBudget); + } else { + return 0; + } +} + +static uint32_t setPositionAssistedClockEstimator(bool enable) { + if (NULL != gGnssAdapter) { + return gGnssAdapter->setPositionAssistedClockEstimatorCommand(enable); + } else { + return 0; + } +} + +static uint32_t gnssUpdateSvConfig( + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) { + if (NULL != gGnssAdapter) { + return gGnssAdapter->gnssUpdateSvConfigCommand( + svTypeConfig, svIdConfig); + } else { + return 0; + } +} + +static uint32_t gnssResetSvConfig() { + if (NULL != gGnssAdapter) { + return gGnssAdapter->gnssResetSvConfigCommand(); + } else { + return 0; + } +} + +static uint32_t configLeverArm(const LeverArmConfigInfo& configInfo){ + if (NULL != gGnssAdapter) { + return gGnssAdapter->configLeverArmCommand(configInfo); + } else { + return 0; + } +} diff --git a/location/Android.mk b/location/Android.mk index bbd6fbd8..2a595414 100644 --- a/location/Android.mk +++ b/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/location/ILocationAPI.h b/location/ILocationAPI.h index 3df6f799..87aa99bd 100644 --- a/location/ILocationAPI.h +++ b/location/ILocationAPI.h @@ -189,6 +189,119 @@ public: LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */ virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) = 0; + + /** @brief + Reset the constellation settings to modem default. + + @param + None + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t resetConstellationConfig() = 0; + + /** @brief + Configure the constellation to be used by the GNSS engine on + modem. + + @param + constellationConfig: specify the constellation configuration + used by GNSS engine. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellations( + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) = 0; + + /** @brief + Enable or disable the constrained time uncertainty feature. + + @param + enable: true to enable the constrained time uncertainty + feature and false to disable the constrainted time + uncertainty feature. + + @param + tuncThreshold: this specifies the time uncertainty threshold + that gps engine need to maintain, in units of milli-seconds. + Default is 0.0 meaning that modem default value of time + uncertainty threshold will be used. This parameter is + ignored when requesting to disable this feature. + + @param + energyBudget: this specifies the power budget that gps + engine is allowed to spend to maintain the time uncertainty. + Default is 0 meaning that GPS engine is not constained by + power budget and can spend as much power as needed. The + parameter need to be specified in units of 0.1 milli watt + second. This parameter is ignored requesting to disable this + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters + are invalid + */ + virtual uint32_t configConstrainedTimeUncertainty( + bool enable, float tuncThreshold = 0.0, + uint32_t energyBudget = 0) = 0; + + /** @brief + Enable or disable position assisted clock estimator feature. + + @param + enable: true to enable position assisted clock estimator and + false to disable the position assisted clock estimator + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configPositionAssistedClockEstimator(bool enable) = 0; + + /** @brief + Sets the lever arm parameters for the vehicle. + + @param + configInfo: lever arm configuration info regarding below two + types of lever arm info: + a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial + measurement unit. + b: lever arm parameters regarding the OPF (output frame) + w.r.t the origin (at the GPS Antenna). Vehicle manufacturers + prefer the position output to be tied to a specific point in + the vehicle rather than where the antenna is placed + (midpoint of the rear axle is typical). + + Caller can choose types of lever arm info to configure via the + leverMarkTypeMask. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) = 0; }; #endif /* ILOCATIONAPI_H */ diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp index 4348c276..7c125b81 100644 --- a/location/LocationAPI.cpp +++ b/location/LocationAPI.cpp @@ -723,3 +723,79 @@ LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data) pthread_mutex_unlock(&gDataMutex); return id; } + +uint32_t LocationControlAPI::resetConstellationConfig() { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->gnssResetSvConfig(); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configConstellations( + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->gnssUpdateSvConfig( + svTypeConfig, svIdConfig); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configConstrainedTimeUncertainty( + bool enable, float tuncThreshold, uint32_t energyBudget) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->setConstrainedTunc(enable, + tuncThreshold, + energyBudget); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->setPositionAssistedClockEstimator(enable); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} + +uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) { + uint32_t id = 0; + pthread_mutex_lock(&gDataMutex); + + if (gData.gnssInterface != NULL) { + id = gData.gnssInterface->configLeverArm(configInfo); + } else { + LOC_LOGe("No gnss interface available for Location Control API"); + } + + pthread_mutex_unlock(&gDataMutex); + return id; +} diff --git a/location/LocationAPI.h b/location/LocationAPI.h index 6f5987ca..f70fc2f8 100644 --- a/location/LocationAPI.h +++ b/location/LocationAPI.h @@ -261,6 +261,119 @@ public: LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */ virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override; + + /** @brief + Reset the constellation settings to modem default. + + @param + None + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t resetConstellationConfig() override; + + /** @brief + Configure the constellation to be used by the GNSS engine on + modem. + + @param + constellationConfig: specify the constellation configuration + used by GNSS engine. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configConstellations( + const GnssSvTypeConfig& svTypeConfig, + const GnssSvIdConfig& svIdConfig) override; + + /** @brief + Enable or disable the constrained time uncertainty feature. + + @param + enable: true to enable the constrained time uncertainty + feature and false to disable the constrainted time + uncertainty feature. + + @param + tuncThreshold: this specifies the time uncertainty threshold + that gps engine need to maintain, in units of milli-seconds. + Default is 0.0 meaning that modem default value of time + uncertainty threshold will be used. This parameter is + ignored when requesting to disable this feature. + + @param + energyBudget: this specifies the power budget that gps + engine is allowed to spend to maintain the time uncertainty. + Default is 0 meaning that GPS engine is not constained by + power budget and can spend as much power as needed. The + parameter need to be specified in units of 0.1 milli watt + second. This parameter is ignored requesting to disable this + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters + are invalid + */ + virtual uint32_t configConstrainedTimeUncertainty( + bool enable, float tuncThreshold = 0.0, + uint32_t energyBudget = 0) override; + + /** @brief + Enable or disable position assisted clock estimator feature. + + @param + enable: true to enable position assisted clock estimator and + false to disable the position assisted clock estimator + feature. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configPositionAssistedClockEstimator(bool enable) override; + + /** @brief + Sets the lever arm parameters for the vehicle. + + @param + configInfo: lever arm configuration info regarding below two + types of lever arm info: + a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial + measurement unit. + b: lever arm parameters regarding the OPF (output frame) + w.r.t the origin (at the GPS Antenna). Vehicle manufacturers + prefer the position output to be tied to a specific point in + the vehicle rather than where the antenna is placed + (midpoint of the rear axle is typical). + + Caller can choose types of lever arm info to configure via the + leverMarkTypeMask. + + @return + A session id that will be returned in responseCallback to + match command with response. This effect is global for all + clients of LocationAPI responseCallback returns: + LOCATION_ERROR_SUCCESS if successful + LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid + */ + virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) override; }; #endif /* LOCATIONAPI_H */ diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h index 17094ab5..65b5e13d 100644 --- a/location/LocationDataTypes.h +++ b/location/LocationDataTypes.h @@ -248,6 +248,7 @@ typedef enum { GNSS_CONFIG_SUPL_VERSION_1_0_0 = 1, GNSS_CONFIG_SUPL_VERSION_2_0_0, GNSS_CONFIG_SUPL_VERSION_2_0_2, + GNSS_CONFIG_SUPL_VERSION_2_0_4, } GnssConfigSuplVersion; // LTE Positioning Profile @@ -567,28 +568,32 @@ typedef enum { 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), + /** BEIDOU B1 RF Band */ + GNSS_SIGNAL_BEIDOU_B1 = (1<<9), + /** BEIDOU B2 RF Band */ + GNSS_SIGNAL_BEIDOU_B2 = (1<<10), /** QZSS L1CA RF Band */ - GNSS_SIGNAL_QZSS_L1CA = (1<<13), + GNSS_SIGNAL_QZSS_L1CA = (1<<11), /** QZSS L1S RF Band */ - GNSS_SIGNAL_QZSS_L1S = (1<<14), + GNSS_SIGNAL_QZSS_L1S = (1<<12), /** QZSS L2 RF Band */ - GNSS_SIGNAL_QZSS_L2 = (1<<15), + GNSS_SIGNAL_QZSS_L2 = (1<<13), /** QZSS L5 RF Band */ - GNSS_SIGNAL_QZSS_L5 = (1<<16), + GNSS_SIGNAL_QZSS_L5 = (1<<14), /** SBAS L1 RF Band */ - GNSS_SIGNAL_SBAS_L1 = (1<<17), + GNSS_SIGNAL_SBAS_L1 = (1<<15), + /** BEIDOU B1I RF Band */ + GNSS_SIGNAL_BEIDOU_B1I = (1<<16), + /** BEIDOU B1C RF Band */ + GNSS_SIGNAL_BEIDOU_B1C = (1<<17), + /** BEIDOU B2I RF Band */ + GNSS_SIGNAL_BEIDOU_B2I = (1<<18), + /** BEIDOU B2AI RF Band */ + GNSS_SIGNAL_BEIDOU_B2AI = (1<<19), /** NAVIC L5 RF Band */ - GNSS_SIGNAL_NAVIC_L5 = (1<<18), + GNSS_SIGNAL_NAVIC_L5 = (1<<20), /** BEIDOU B2A_Q RF Band */ - GNSS_SIGNAL_BEIDOU_B2AQ = (1<<19) + GNSS_SIGNAL_BEIDOU_B2AQ = (1<<21), } GnssSignalTypeBits; #define GNSS_SIGNAL_TYPE_MASK_ALL\ @@ -654,6 +659,8 @@ typedef enum { DEAD_RECKONING_ENGINE = (1 << 1), PRECISE_POSITIONING_ENGINE = (1 << 2) } PositioningEngineBits; +#define POSITION_ENGINE_MASK_ALL \ + (STANDARD_POSITIONING_ENGINE|DEAD_RECKONING_ENGINE|PRECISE_POSITIONING_ENGINE) typedef uint64_t GnssDataMask; typedef enum { @@ -1182,6 +1189,13 @@ typedef struct { // GAL - SV 301 maps to bit 0 #define GNSS_SV_CONFIG_GAL_INITIAL_SV_ID 301 uint64_t galBlacklistSvMask; + + // SBAS - SV 120 to 158, maps to 0 to 38 + // SV 183 to 191, maps to 39 to 47 +#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120 +#define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39 +#define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183 + uint64_t sbasBlacklistSvMask; } GnssSvIdConfig; struct GnssConfig{ @@ -1309,6 +1323,66 @@ struct LocationSystemInfo { LeapSecondSystemInfo leapSecondSysInfo; }; +/* Mask indicating enabled or disabled constellations */ +typedef uint64_t GnssSvTypesMask; +typedef enum { + GNSS_SV_TYPES_MASK_GLO_BIT = (1<<0), + GNSS_SV_TYPES_MASK_BDS_BIT = (1<<1), + GNSS_SV_TYPES_MASK_QZSS_BIT = (1<<2), + GNSS_SV_TYPES_MASK_GAL_BIT = (1<<3), + GNSS_SV_TYPES_MASK_NAVIC_BIT = (1<<4), +} GnssSvTypesMaskBits; + +/* This SV Type config is injected directly to GNSS Adapter + * bypassing Location API */ +typedef struct { + uint32_t size; // set to sizeof(GnssSvTypeConfig) + // Enabled Constellations + GnssSvTypesMask enabledSvTypesMask; + // Disabled Constellations + GnssSvTypesMask blacklistedSvTypesMask; +} GnssSvTypeConfig; + +// Specify parameters related to lever arm +struct LeverArmParams { + // Offset along the vehicle forward axis + float forwardOffsetMeters; + // Offset along the vehicle starboard axis + float sidewaysOffsetMeters; + // Offset along the vehicle up axis + float upOffsetMeters; +}; + +typedef uint32_t LeverArmTypeMask; + +enum LeverArmTypeBits { + // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t + // the origin (at the GPS Antenna) + LEVER_ARM_TYPE_GNSS_TO_VRP_BIT = (1<<0), + // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU + // e.g.: inertial measurement unit for DR (dead reckoning + // engine) + LEVER_ARM_TYPE_DR_IMU_TO_GNSS_BIT = (1<<1), + // Lever arm regarding GNSS Antenna w.r.t the origin at the + // IMU (inertial measurement unit) for VEPP (vision enhanced + // precise positioning engine) + LEVER_ARM_TYPE_VEPP_IMU_TO_GNSS_BIT = (1<<2) +}; + +struct LeverArmConfigInfo { + // Valid mask for the types of lever arm parameters provided + LeverArmTypeMask leverArmValidMask; + // Lever arm regarding the VRP (Vehicle Reference Point) w.r.t the origin + // (at the GPS Antenna) + LeverArmParams gnssToVRP; + // Lever arm parameters regarding GNSS Antenna w.r.t the origin at the IMU + // (inertial measurement unit) for DR (dead reckoning engine) + LeverArmParams drImuToGnss; + // Lever arm regarding GNSS Antenna w.r.t the origin at the IMU + // (inertial measurement unit) for VEPP (vision enhanced precise position engine) + LeverArmParams veppImuToGnss; +}; + /* Provides the capabilities of the system capabilities callback is called once soon after createInstance is called */ typedef std::function 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))) { @@ -894,9 +935,17 @@ 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) && + (config_mask & CONFIG_MASK_SOCID_CHECK) && (child_proc[j].proc_status != DISABLED_FROM_CONF) && (child_proc[j].proc_status != DISABLED_VIA_VENDOR_ENHANCED_CHECK)) { diff --git a/utils/loc_nmea.cpp b/utils/loc_nmea.cpp index 41a707dc..9ee27164 100644 --- a/utils/loc_nmea.cpp +++ b/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 @@ -782,8 +782,13 @@ static void loc_nmea_generate_GSV(const GnssSvNotification &svNotify, 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 @@ -1028,47 +1033,56 @@ SIDE EFFECTS ===========================================================================*/ static void loc_nmea_get_fix_quality(const UlpLocation & location, const GpsLocationExtended & locationExtended, - char & ggaGpsQuality, + bool custom_gga_fix_quality, + char ggaGpsQuality[3], char & rmcModeIndicator, char & vtgModeIndicator) { - ggaGpsQuality = '0'; - rmcModeIndicator = 'N'; - vtgModeIndicator = 'N'; + 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)){ - ggaGpsQuality = '0'; // 0 means no fix - rmcModeIndicator = 'N'; - vtgModeIndicator = 'N'; 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 = '2'; // 2 means DGPS fix + 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 = '4'; // 4 means RTK Fixed fix + 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 = '5'; // 5 means RTK float fix + 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 = '2'; // 2 means DGPS fix + 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 = '2'; // 2 means DGPS fix + ggaGpsQuality[0] = '2'; // 2 means DGPS fix rmcModeIndicator = 'D'; // D means differential vtgModeIndicator = 'D'; // D means differential break; @@ -1077,12 +1091,12 @@ static void loc_nmea_get_fix_quality(const UlpLocation & location, // 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 = '1'; // 1 means GPS + 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 = '6'; // 6 means estimated (dead reckoning) + ggaGpsQuality[0] = '6'; // 6 means estimated (dead reckoning) rmcModeIndicator = 'E'; // E means estimated (dead reckoning) vtgModeIndicator = 'E'; // E means estimated (dead reckoning) break; @@ -1090,7 +1104,54 @@ static void loc_nmea_get_fix_quality(const UlpLocation & location, } } while (0); - LOC_LOGv("gps quality: %c, rmc mode indicator: %c, vtg mode indicator: %c", + 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); } @@ -1122,6 +1183,7 @@ 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(); @@ -1133,7 +1195,8 @@ void loc_nmea_generate_pos(const UlpLocation &location, (location, locationExtended, systemInfo, utcPosTimestamp); time_t utcTime(utcPosTimestamp/1000); - tm * pTm = gmtime(&utcTime); + struct tm result; + tm * pTm = gmtime_r(&utcTime, &result); if (NULL == pTm) { LOC_LOGE("gmtime failed"); return; @@ -1265,10 +1328,18 @@ void loc_nmea_generate_pos(const UlpLocation &location, talker[1] = sv_meta.talker[1]; } - char ggaGpsQuality = '0'; + // if svUsedCount is 0, it means we do not generate any GSA sentence yet. + // in this case, generate an empty GSA sentence + if (svUsedCount == 0) { + strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,,", sizeof(sentence)); + length = loc_nmea_put_checksum(sentence, sizeof(sentence)); + nmeaArraystr.push_back(sentence); + } + + char ggaGpsQuality[3] = {'0', '\0', '\0'}; char rmcModeIndicator = 'N'; char vtgModeIndicator = 'N'; - loc_nmea_get_fix_quality(location, locationExtended, + loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality, ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); // ------------------- @@ -1377,8 +1448,19 @@ void loc_nmea_generate_pos(const UlpLocation &location, pMarker = sentence_RMC; lengthRemaining = sizeof(sentence_RMC); - length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," , - talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10); + bool validFix = ((0 != sv_cache_info.gps_used_mask) || + (0 != sv_cache_info.glo_used_mask) || + (0 != sv_cache_info.gal_used_mask) || + (0 != sv_cache_info.qzss_used_mask) || + (0 != sv_cache_info.bds_used_mask)); + + if (validFix) { + length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A,", + talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); + } else { + length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,V,", + talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); + } if (length < 0 || length >= lengthRemaining) { @@ -1519,8 +1601,6 @@ void loc_nmea_generate_pos(const UlpLocation &location, // 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)); @@ -1767,12 +1847,12 @@ void loc_nmea_generate_pos(const UlpLocation &location, svUsedCount = MAX_SATELLITES_IN_USE; if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) { - length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", + length = snprintf(pMarker, lengthRemaining, "%s,%02d,%.1f,", ggaGpsQuality, svUsedCount, locationExtended.hdop); } else { // no hdop - length = snprintf(pMarker, lengthRemaining, "%c,%02d,,", + length = snprintf(pMarker, lengthRemaining, "%s,%02d,,", ggaGpsQuality, svUsedCount); } @@ -1901,7 +1981,7 @@ 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++; @@ -1919,7 +1999,7 @@ 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++; @@ -1937,7 +2017,7 @@ 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++; @@ -1955,7 +2035,9 @@ 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++; @@ -1973,9 +2055,10 @@ 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){ + if ((GNSS_SIGNAL_BEIDOU_B2AI == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask) || + (GNSS_SIGNAL_BEIDOU_B2AQ == svNotify.gnssSvs[svNumber - 1].gnssSignalTypeMask)) { sv_cache_info.bds_b2_count++; } else { // GNSS_SIGNAL_BEIDOU_B1I or default @@ -1991,7 +2074,8 @@ void loc_nmea_generate_sv(const GnssSvNotification &svNotify, (svNotify.gnssSvs[svNumber - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) { - sv_cache_info.navic_used_mask |= (1 << (svNotify.gnssSvs[svNumber - 1].svId - 1)); + sv_cache_info.navic_used_mask |= + (1ULL << (svNotify.gnssSvs[svNumber - 1].svId - 1)); } // GNSS_SIGNAL_NAVIC_L5 is the only signal type for NAVIC sv_cache_info.navic_l5_count++; diff --git a/utils/loc_nmea.h b/utils/loc_nmea.h index c6c83db4..a9cafb76 100644 --- a/utils/loc_nmea.h +++ b/utils/loc_nmea.h @@ -79,6 +79,7 @@ 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/utils/loc_target.cpp b/utils/loc_target.cpp index f6fd728a..3ee42e62 100644 --- a/utils/loc_target.cpp +++ b/utils/loc_target.cpp @@ -80,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); @@ -130,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]; @@ -155,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)); diff --git a/utils/loc_target.h b/utils/loc_target.h index 172b4752..2dcd895e 100644 --- a/utils/loc_target.h +++ b/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/utils/log_util.h b/utils/log_util.h index ed7e19e1..192baebb 100644 --- a/utils/log_util.h +++ b/utils/log_util.h @@ -176,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) @@ -193,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)