diff options
author | haohuang <haohuang@codeaurora.org> | 2020-11-09 22:12:37 +0800 |
---|---|---|
committer | haohuang <haohuang@codeaurora.org> | 2020-12-01 13:10:17 +0800 |
commit | 3dbdbe37aba5d1a73c3ae99e0a81d8f7d3e66698 (patch) | |
tree | 034cd77824d89ddb6f442ad4607bb7f08bafaf2d | |
parent | e437e1117e00aa9643f994e58e1f23ddbbdeb930 (diff) |
A new class to estimate ElapsedRealTime in LocApiBase
1, Implement a method to estimate ElapsedRealTime
if Qtimer is not valid. This method uses a default
initial value and AP boot time/UTC time and Modem
gps time/Measurement time.
2, Move the ElapsedRealTime calculation & estimation
from Hidl API layer to LocApiV02 layer.
Change-Id: I523d64d00d488cca0c053f9c636c34b01214f1a9
CRs-Fixed: 2817942
-rw-r--r-- | android/2.0/location_api/LocationUtil.cpp | 107 | ||||
-rw-r--r-- | android/2.0/location_api/LocationUtil.h | 1 | ||||
-rw-r--r-- | android/2.0/location_api/MeasurementAPIClient.cpp | 80 | ||||
-rw-r--r-- | android/2.1/location_api/LocationUtil.cpp | 107 | ||||
-rw-r--r-- | android/2.1/location_api/LocationUtil.h | 1 | ||||
-rw-r--r-- | android/2.1/location_api/MeasurementAPIClient.cpp | 82 | ||||
-rw-r--r-- | core/LocApiBase.cpp | 139 | ||||
-rw-r--r-- | core/LocApiBase.h | 23 |
8 files changed, 200 insertions, 340 deletions
diff --git a/android/2.0/location_api/LocationUtil.cpp b/android/2.0/location_api/LocationUtil.cpp index fe8d22c..0742f27 100644 --- a/android/2.0/location_api/LocationUtil.cpp +++ b/android/2.0/location_api/LocationUtil.cpp @@ -84,109 +84,22 @@ void convertGnssLocation(Location& in, V1_0::GnssLocation& out) out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp); } -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos) -{ - struct timespec sinceBootTime; - struct timespec sinceBootTimeTest; - bool clockGetTimeSuccess = false; - const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000; - const uint32_t MAX_GET_TIME_COUNT = 20; - /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption - or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */ - for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) { - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) { - break; - }; - if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) { - break; - } - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { - break; - }; - sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec; - int64_t sinceBootTimeTestNanos = - sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec; - int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos; - - /* sinceBootTime and sinceBootTimeTest should have a close value if there was no - interruption or context switch between clock_gettime for CLOCK_BOOTIME and - clock_gettime for CLOCK_REALTIME */ - if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) { - clockGetTimeSuccess = true; - break; - } else { - LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...", - sinceBootTimeDeltaNanos, i + 1); - } - } - return clockGetTimeSuccess; -} - void convertGnssLocation(Location& in, V2_0::GnssLocation& out) { memset(&out, 0, sizeof(V2_0::GnssLocation)); convertGnssLocation(in, out.v1_0); - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.elapsedRealTime; - } - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; - } - } else { - int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec; - int64_t locationTimeNanos = in.timestamp*1000000; - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " locationTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, locationTimeNanos); - if (currentTimeNanos >= locationTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos; - LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user setting - // wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, to - // verify if user change the sys time - out.elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } + if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + out.elapsedRealtime.timestampNs = in.elapsedRealTime; + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; + LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 "" + " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" + " out.elapsedRealtime.flags=0x%X", + out.elapsedRealtime.timestampNs, + out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } - LOC_LOGv("out.elapsedRealtime.timestampNs=%" PRIi64 "" - " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" - " out.elapsedRealtime.flags=0x%X", - out.elapsedRealtime.timestampNs, - out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } void convertGnssLocation(const V1_0::GnssLocation& in, Location& out) diff --git a/android/2.0/location_api/LocationUtil.h b/android/2.0/location_api/LocationUtil.h index 3c34514..70729e4 100644 --- a/android/2.0/location_api/LocationUtil.h +++ b/android/2.0/location_api/LocationUtil.h @@ -51,7 +51,6 @@ void convertGnssSvid(GnssMeasurementsData& in, int16_t& out); void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos); } // namespace implementation } // namespace V2_0 diff --git a/android/2.0/location_api/MeasurementAPIClient.cpp b/android/2.0/location_api/MeasurementAPIClient.cpp index a32b1cd..425415f 100644 --- a/android/2.0/location_api/MeasurementAPIClient.cpp +++ b/android/2.0/location_api/MeasurementAPIClient.cpp @@ -437,78 +437,16 @@ static void convertGnssData_2_0(GnssMeasurementsNotification& in, static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in, ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime) { - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.clock.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.clock.elapsedRealTime; - } - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.clock.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.clock.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; - } - } else { - const uint32_t UTC_TO_GPS_SECONDS = 315964800; - - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) { - int64_t currentTimeNanos = currentTime.tv_sec * 1000000000 + currentTime.tv_nsec; - int64_t measTimeNanos = (int64_t)in.clock.timeNs - (int64_t)in.clock.fullBiasNs - - (int64_t)in.clock.biasNs - (int64_t)in.clock.leapSecond * 1000000000 - + (int64_t)UTC_TO_GPS_SECONDS * 1000000000; - - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " measTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, measTimeNanos); - if (currentTimeNanos >= measTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - measTimeNanos; - LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user - // setting wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - elapsedRealtime.flags |= - V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, - // to verify if user change the sys time - elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } else { - LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp"); - } - } + if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + elapsedRealtime.timestampNs = in.clock.elapsedRealTime; + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; + LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 "" + " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", + elapsedRealtime.timestampNs, + elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } - LOC_LOGv("elapsedRealtime.timestampNs=%" PRIi64 "" - " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", - elapsedRealtime.timestampNs, - elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in, diff --git a/android/2.1/location_api/LocationUtil.cpp b/android/2.1/location_api/LocationUtil.cpp index 4371119..e5b49b2 100644 --- a/android/2.1/location_api/LocationUtil.cpp +++ b/android/2.1/location_api/LocationUtil.cpp @@ -85,109 +85,22 @@ void convertGnssLocation(Location& in, V1_0::GnssLocation& out) out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp); } -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos) -{ - struct timespec sinceBootTime; - struct timespec sinceBootTimeTest; - bool clockGetTimeSuccess = false; - const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000; - const uint32_t MAX_GET_TIME_COUNT = 20; - /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption - or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */ - for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) { - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) { - break; - }; - if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) { - break; - } - if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { - break; - }; - sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec; - int64_t sinceBootTimeTestNanos = - sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec; - int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos; - - /* sinceBootTime and sinceBootTimeTest should have a close value if there was no - interruption or context switch between clock_gettime for CLOCK_BOOTIME and - clock_gettime for CLOCK_REALTIME */ - if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) { - clockGetTimeSuccess = true; - break; - } else { - LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...", - sinceBootTimeDeltaNanos, i + 1); - } - } - return clockGetTimeSuccess; -} - void convertGnssLocation(Location& in, V2_0::GnssLocation& out) { memset(&out, 0, sizeof(V2_0::GnssLocation)); convertGnssLocation(in, out.v1_0); - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.elapsedRealTime; - } - LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " in.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; - } - } else { - int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec; - int64_t locationTimeNanos = in.timestamp*1000000; - LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " locationTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, locationTimeNanos); - if (currentTimeNanos >= locationTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos; - LOC_LOGd("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user setting - // wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, to - // verify if user change the sys time - out.elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } + if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) { + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + out.elapsedRealtime.timestampNs = in.elapsedRealTime; + out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc; + LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 "" + " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" + " out.elapsedRealtime.flags=0x%X", + out.elapsedRealtime.timestampNs, + out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } - LOC_LOGd("out.elapsedRealtime.timestampNs=%" PRIi64 "" - " out.elapsedRealtime.timeUncertaintyNs=%" PRIi64 "" - " out.elapsedRealtime.flags=0x%X", - out.elapsedRealtime.timestampNs, - out.elapsedRealtime.timeUncertaintyNs, out.elapsedRealtime.flags); } void convertGnssLocation(const V1_0::GnssLocation& in, Location& out) diff --git a/android/2.1/location_api/LocationUtil.h b/android/2.1/location_api/LocationUtil.h index fde1595..2d95a2d 100644 --- a/android/2.1/location_api/LocationUtil.h +++ b/android/2.1/location_api/LocationUtil.h @@ -56,7 +56,6 @@ void convertGnssSvid(GnssMeasurementsData& in, int16_t& out); void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); -bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos); void convertSingleSatCorrections(const SingleSatCorrection& in, GnssSingleSatCorrection& out); void convertMeasurementCorrections(const MeasurementCorrectionsV1_0& in, GnssMeasurementCorrections& out); diff --git a/android/2.1/location_api/MeasurementAPIClient.cpp b/android/2.1/location_api/MeasurementAPIClient.cpp index 5869774..0028074 100644 --- a/android/2.1/location_api/MeasurementAPIClient.cpp +++ b/android/2.1/location_api/MeasurementAPIClient.cpp @@ -623,80 +623,16 @@ static void convertGnssData_2_1(GnssMeasurementsNotification& in, static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in, ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime) { - struct timespec currentTime; - int64_t sinceBootTimeNanos; - - if (getCurrentTime(currentTime, sinceBootTimeNanos)) { - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { - uint64_t qtimerDiff = 0; - uint64_t qTimerTickCount = getQTimerTickCount(); - if (qTimerTickCount >= in.clock.elapsedRealTime) { - qtimerDiff = qTimerTickCount - in.clock.elapsedRealTime; - } - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " in.clock.elapsedRealTime=%" PRIi64 "" - " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", - sinceBootTimeNanos, in.clock.elapsedRealTime, qTimerTickCount, qtimerDiff); - uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); - - /* If the time difference between Qtimer on modem side and Qtimer on AP side - is greater than one second we assume this is a dual-SoC device such as - Kona and will try to get Qtimer on modem side and on AP side and - will adjust our difference accordingly */ - if (qTimerDiffNanos > 1000000000) { - uint64_t qtimerDelta = getQTimerDeltaNanos(); - if (qTimerDiffNanos >= qtimerDelta) { - qTimerDiffNanos -= qtimerDelta; - } - } - - if (sinceBootTimeNanos >= qTimerDiffNanos) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - qTimerDiffNanos; - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; - } - } else { - const uint32_t UTC_TO_GPS_SECONDS = 315964800; - - if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT && - in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) { - int64_t currentTimeNanos = currentTime.tv_sec * 1000000000 + currentTime.tv_nsec; - int64_t measTimeNanos = (int64_t)in.clock.timeNs - (int64_t)in.clock.fullBiasNs - - (int64_t)in.clock.biasNs - (int64_t)in.clock.leapSecond * 1000000000 - + (int64_t)UTC_TO_GPS_SECONDS * 1000000000; - - LOC_LOGv("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" - " measTimeNanos:%" PRIi64 "", - sinceBootTimeNanos, currentTimeNanos, measTimeNanos); - if (currentTimeNanos >= measTimeNanos) { - int64_t ageTimeNanos = currentTimeNanos - measTimeNanos; - LOC_LOGv("ageTimeNanos:%" PRIi64 ")", ageTimeNanos); - // the max trusted propagation time 100ms for ageTimeNanos to avoid user - // setting wrong time, it will affect elapsedRealtimeNanos - if (ageTimeNanos <= 100000000) { - elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; - elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos; - elapsedRealtime.flags |= - V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; - // time uncertainty is 1 ms since it is calculated from utc time that - // is in ms - // time uncertainty is the max value between abs(AP_UTC - MP_UTC) and 100ms, - // to verify if user change the sys time - elapsedRealtime.timeUncertaintyNs = - std::max(ageTimeNanos, (int64_t)100000000); - } - } - } else { - LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp"); - } - } + if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) { + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS; + elapsedRealtime.timestampNs = in.clock.elapsedRealTime; + elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS; + elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc; + LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 "" + " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", + elapsedRealtime.timestampNs, + elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } - LOC_LOGv("elapsedRealtime.timestampNs=%" PRIi64 "" - " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X", - elapsedRealtime.timestampNs, - elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags); } } // namespace implementation diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index dbe4590..2413d05 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -36,6 +36,7 @@ #include <LocAdapterBase.h> #include <log_util.h> #include <LocContext.h> +#include <loc_misc_utils.h> namespace loc_core { @@ -927,4 +928,142 @@ DEFAULT_IMPL() void LocApiBase:: getConstellationMultiBandConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/) DEFAULT_IMPL() + +int64_t ElapsedRealtimeEstimator::getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos, + bool isCurDataTimeTrustable, uint32_t tbf) { + //The algorithm works follow below steps: + //When isCurDataTimeTrustable is meet (means Modem timestamp is already stable), + //1, Wait for mFixTimeStablizationThreshold fixes; While waiting for modem time + // stable, we set the traveltime to a default value; + //2, When the mFixTimeStablizationThreshold fix comes, we think now the mode time + // is already stable, calculate the initial AP-Modem clock diff(mCurrentClockDiff) + // using formula: + // mCurrentClockDiff = currentTimeNanos - locationTimeNanos - currentTravelTimeNanos + //3, since then, when the nth fix comes, + // 3.1 First update mCurrentClockDiff using below formula: + // mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos) + // - (mPrevUtcTimeNanos - mPrevBootTimeNanos) + // 3.2 Calculate currentTravelTimeNanos: + // currentTravelTimeNanos = currentTimeNanos - locationTimeNanos - mCurrentClockDiff + //4, It is possible that locationTimeNanos will jump, + // reset mFixTimeStablizationThreshold to default value, jump to step 2 to continue. + + int64_t currentTravelTimeNanos = mInitialTravelTime; + struct timespec currentTime; + int64_t sinceBootTimeNanos; + if (getCurrentTime(currentTime, sinceBootTimeNanos)) { + if (isCurDataTimeTrustable) { + if (tbf > 0 && tbf != curDataTimeNanos - mPrevDataTimeNanos) { + mFixTimeStablizationThreshold = 5; + } + int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec; + LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 "" + " locationTimeNanos:%" PRIi64 "", + sinceBootTimeNanos, currentTimeNanos, curDataTimeNanos); + if (mFixTimeStablizationThreshold == 0) { + currentTravelTimeNanos = mInitialTravelTime; + mCurrentClockDiff = currentTimeNanos - curDataTimeNanos - currentTravelTimeNanos; + } else if (mFixTimeStablizationThreshold < 0) { + mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos) + - (mPrevUtcTimeNanos - mPrevBootTimeNanos); + currentTravelTimeNanos = currentTimeNanos - curDataTimeNanos - mCurrentClockDiff; + } + + mPrevUtcTimeNanos = currentTimeNanos; + mPrevBootTimeNanos = sinceBootTimeNanos; + mPrevDataTimeNanos = curDataTimeNanos; + mFixTimeStablizationThreshold--; + } + } else { + return -1; + } + LOC_LOGd("Estimated travel time: %" PRIi64 "", currentTravelTimeNanos); + return (sinceBootTimeNanos - currentTravelTimeNanos); +} + +void ElapsedRealtimeEstimator::reset() { + mCurrentClockDiff = 0; + mPrevDataTimeNanos = 0; + mPrevUtcTimeNanos = 0; + mPrevBootTimeNanos = 0; + mFixTimeStablizationThreshold = 5; +} + +int64_t ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin) { + struct timespec currentTime; + int64_t sinceBootTimeNanos; + int64_t elapsedRealTimeNanos; + + if (getCurrentTime(currentTime, sinceBootTimeNanos)) { + uint64_t qtimerDiff = 0; + uint64_t qTimerTickCount = getQTimerTickCount(); + if (qTimerTickCount >= qtimerTicksAtOrigin) { + qtimerDiff = qTimerTickCount - qtimerTicksAtOrigin; + } + LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " qtimerTicksAtOrigin=%" PRIi64 "" + " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "", + sinceBootTimeNanos, qtimerTicksAtOrigin, qTimerTickCount, qtimerDiff); + uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff)); + + /* If the time difference between Qtimer on modem side and Qtimer on AP side + is greater than one second we assume this is a dual-SoC device such as + Kona and will try to get Qtimer on modem side and on AP side and + will adjust our difference accordingly */ + if (qTimerDiffNanos > 1000000000) { + uint64_t qtimerDelta = getQTimerDeltaNanos(); + if (qTimerDiffNanos >= qtimerDelta) { + qTimerDiffNanos -= qtimerDelta; + } + } + + LOC_LOGd("Qtimer travel time: %" PRIi64 "", qTimerDiffNanos); + if (sinceBootTimeNanos >= qTimerDiffNanos) { + elapsedRealTimeNanos = sinceBootTimeNanos - qTimerDiffNanos; + } else { + elapsedRealTimeNanos = -1; + } + } else { + elapsedRealTimeNanos = -1; + } + return elapsedRealTimeNanos; +} + +bool ElapsedRealtimeEstimator::getCurrentTime( + struct timespec& currentTime, int64_t& sinceBootTimeNanos) +{ + struct timespec sinceBootTime; + struct timespec sinceBootTimeTest; + bool clockGetTimeSuccess = false; + const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000; + const uint32_t MAX_GET_TIME_COUNT = 20; + /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption + or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */ + for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) { + if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) { + break; + }; + if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0) { + break; + } + if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) { + break; + }; + sinceBootTimeNanos = sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec; + int64_t sinceBootTimeTestNanos = + sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec; + int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos; + + /* sinceBootTime and sinceBootTimeTest should have a close value if there was no + interruption or context switch between clock_gettime for CLOCK_BOOTIME and + clock_gettime for CLOCK_REALTIME */ + if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) { + clockGetTimeSuccess = true; + break; + } else { + LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...", + sinceBootTimeDeltaNanos, i + 1); + } + } + return clockGetTimeSuccess; +} } // namespace loc_core diff --git a/core/LocApiBase.h b/core/LocApiBase.h index 95c0a38..b58e60d 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -41,6 +41,8 @@ #else #include <unordered_map> #endif +#include <inttypes.h> +#include <functional> using namespace loc_util; @@ -344,6 +346,27 @@ public: LocApiResponse* adapterResponse=nullptr); }; +class ElapsedRealtimeEstimator { +private: + int64_t mCurrentClockDiff; + int64_t mPrevUtcTimeNanos; + int64_t mPrevBootTimeNanos; + int64_t mFixTimeStablizationThreshold; + int64_t mInitialTravelTime; + int64_t mPrevDataTimeNanos; +public: + + ElapsedRealtimeEstimator(int64_t travelTimeNanosEstimate): + mInitialTravelTime(travelTimeNanosEstimate) {reset();} + int64_t getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos, + bool isCurDataTimeTrustable, uint32_t tbf); + inline int64_t getElapsedRealtimeUncNanos() { return 5000000;} + void reset(); + + static int64_t getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin); + static bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos); +}; + typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask, ContextBase *context); |