From f80980210e4b9ba5da41bc7f615943e164c68f39 Mon Sep 17 00:00:00 2001 From: Dante Russo Date: Mon, 30 Sep 2019 16:24:03 -0700 Subject: Assure accurate elapsedRealTimeNanos calculations If a context switch or interrupt happens between getting current time and getting boot time, this can throw off the calculation for the elapsedRealTimeNanos timestamp. Avoid this by retrying if there is a large enough delta between getting current time and getting boot time. Change-Id: I47d7a99b480423a50eaf951a904f21928587eda6 CRs-fixed: 2541719 --- android/2.0/location_api/LocationUtil.cpp | 41 ++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'android') diff --git a/android/2.0/location_api/LocationUtil.cpp b/android/2.0/location_api/LocationUtil.cpp index 38a083a..8a30066 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) -- cgit v1.2.3