Use Qtimer to improve ElapsedRealTimeNanos accuracy
Compute ElapsedRealTimeNanos as a difference between
timestamp in the modem and timestamp in AP, both
computed using Qtimer.
Change-Id: I734c26341f61549180bef3e2d3bdd7e145cec7e0
CRs-fixed: 2656142
diff --git a/android/2.1/location_api/LocationUtil.cpp b/android/2.1/location_api/LocationUtil.cpp
index 2f8aaaa..47c3884 100644
--- a/android/2.1/location_api/LocationUtil.cpp
+++ b/android/2.1/location_api/LocationUtil.cpp
@@ -30,6 +30,7 @@
#include <LocationUtil.h>
#include <log_util.h>
#include <inttypes.h>
+#include <loc_misc_utils.h>
namespace android {
namespace hardware {
@@ -125,31 +126,38 @@
{
memset(&out, 0, sizeof(V2_0::GnssLocation));
convertGnssLocation(in, out.v1_0);
+ if (in.flags & LOCATION_HAS_ELAPSED_REAL_TIME) {
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ uint64_t qtimerDiff = in.elapsedRealTime - getQTimerTickCount();
+ out.elapsedRealtime.timestampNs = qTimerTicksToNanos(double(qtimerDiff));
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ out.elapsedRealtime.timeUncertaintyNs = in.elapsedRealTimeUnc;
+ } else {
+ struct timespec currentTime;
+ int64_t sinceBootTimeNanos;
- struct timespec currentTime;
- int64_t sinceBootTimeNanos;
-
- if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
- int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
- int64_t locationTimeNanos = in.timestamp*1000000;
- LOC_LOGD("%s]: sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
+ if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
+ int64_t currentTimeNanos = currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
+ int64_t locationTimeNanos = in.timestamp*1000000;
+ LOC_LOGD("%s]: sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
" locationTimeNanos:%" PRIi64 "",
__FUNCTION__, sinceBootTimeNanos, currentTimeNanos, locationTimeNanos);
- if (currentTimeNanos >= locationTimeNanos) {
- int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos;
- LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
- if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
- out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
- out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
- out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
- // time uncertainty is 1 ms since it is calculated from utc time that is in ms
- out.elapsedRealtime.timeUncertaintyNs = 1000000;
- LOC_LOGD("%s]: timestampNs:%" PRIi64 ")",
+ if (currentTimeNanos >= locationTimeNanos) {
+ int64_t ageTimeNanos = currentTimeNanos - locationTimeNanos;
+ LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
+ if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
+ out.elapsedRealtime.flags |= ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ // time uncertainty is 1 ms since it is calculated from utc time that is in ms
+ out.elapsedRealtime.timeUncertaintyNs = 1000000;
+ LOC_LOGD("%s]: timestampNs:%" PRIi64 ")",
__FUNCTION__, out.elapsedRealtime.timestampNs);
+ }
}
+ } else {
+ LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
}
- } else {
- LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
}
}
diff --git a/android/2.1/location_api/MeasurementAPIClient.cpp b/android/2.1/location_api/MeasurementAPIClient.cpp
index edf422c..6479d62 100644
--- a/android/2.1/location_api/MeasurementAPIClient.cpp
+++ b/android/2.1/location_api/MeasurementAPIClient.cpp
@@ -36,6 +36,7 @@
#include "LocationUtil.h"
#include "MeasurementAPIClient.h"
+#include <loc_misc_utils.h>
namespace android {
namespace hardware {
@@ -68,6 +69,8 @@
static void convertGnssMeasurementsState(GnssMeasurementsStateMask& in,
::android::hardware::hidl_bitfield
<V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out);
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);
MeasurementAPIClient::MeasurementAPIClient() :
mGnssMeasurementCbIface(nullptr),
@@ -332,7 +335,7 @@
static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
{
- memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock));
+ memset(&out, 0, sizeof(out));
if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
@@ -361,6 +364,7 @@
static void convertGnssClock_2_1(GnssMeasurementsClock& in,
V2_1::IGnssMeasurementCallback::GnssClock& out)
{
+ memset(&out, 0, sizeof(out));
convertGnssClock(in, out.v1_0);
convertGnssConstellationType(in.referenceSignalTypeForIsb.svType,
out.referenceSignalTypeForIsb.constellation);
@@ -374,6 +378,7 @@
static void convertGnssData(GnssMeasurementsNotification& in,
V1_0::IGnssMeasurementCallback::GnssData& out)
{
+ memset(&out, 0, sizeof(out));
out.measurementCount = in.count;
if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
@@ -389,6 +394,7 @@
static void convertGnssData_1_1(GnssMeasurementsNotification& in,
V1_1::IGnssMeasurementCallback::GnssData& out)
{
+ memset(&out, 0, sizeof(out));
out.measurements.resize(in.count);
for (size_t i = 0; i < in.count; i++) {
convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
@@ -401,6 +407,7 @@
static void convertGnssData_2_0(GnssMeasurementsNotification& in,
V2_0::IGnssMeasurementCallback::GnssData& out)
{
+ memset(&out, 0, sizeof(out));
out.measurements.resize(in.count);
for (size_t i = 0; i < in.count; i++) {
convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
@@ -413,46 +420,13 @@
convertGnssMeasurementsState(in.measurements[i].stateMask, out.measurements[i].state);
}
convertGnssClock(in.clock, out.clock);
-
- const uint32_t UTC_TO_GPS_SECONDS = 315964800;
- struct timespec currentTime;
- int64_t sinceBootTimeNanos;
-
- if (getCurrentTime(currentTime, sinceBootTimeNanos) &&
- 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_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
- " measTimeNanos:%" PRIi64 "",
- sinceBootTimeNanos, currentTimeNanos, measTimeNanos);
- if (currentTimeNanos >= measTimeNanos) {
- int64_t ageTimeNanos = currentTimeNanos - measTimeNanos;
- LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
- if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
- out.elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
- out.elapsedRealtime.timestampNs = sinceBootTimeNanos - ageTimeNanos;
- out.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
- out.elapsedRealtime.timeUncertaintyNs = 1000000;
- LOC_LOGd("timestampNs:%" PRIi64 ") timeUncertaintyNs:%" PRIi64 ")",
- out.elapsedRealtime.timestampNs,
- out.elapsedRealtime.timeUncertaintyNs);
- }
- }
- } else {
- LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
- }
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
}
static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& inCodeType,
char* inOtherCodeTypeName, ::android::hardware::hidl_string& out)
{
+ memset(&out, 0, sizeof(out));
switch(inCodeType) {
case GNSS_MEASUREMENTS_CODE_TYPE_A:
out = "A";
@@ -507,6 +481,7 @@
::android::hardware::hidl_bitfield
<V1_1::IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState>& out)
{
+ memset(&out, 0, sizeof(out));
if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
out |= IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
if (in & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
@@ -522,6 +497,7 @@
::android::hardware::hidl_bitfield
<V2_0::IGnssMeasurementCallback::GnssMeasurementState>& out)
{
+ memset(&out, 0, sizeof(out));
if (in & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
out |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
if (in & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
@@ -561,6 +537,7 @@
static void convertGnssData_2_1(GnssMeasurementsNotification& in,
V2_1::IGnssMeasurementCallback::GnssData& out)
{
+ memset(&out, 0, sizeof(out));
out.measurements.resize(in.count);
for (size_t i = 0; i < in.count; i++) {
out.measurements[i].flags = 0;
@@ -628,6 +605,54 @@
}
}
convertGnssClock_2_1(in.clock, out.clock);
+ convertElapsedRealtimeNanos(in, out.elapsedRealtime);
+}
+
+static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
+ ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
+{
+ if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
+ uint64_t qtimerDiff = in.clock.elapsedRealTime - getQTimerTickCount();
+ elapsedRealtime.timestampNs = qTimerTicksToNanos(double(qtimerDiff));
+ elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
+ elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
+ } else {
+ const uint32_t UTC_TO_GPS_SECONDS = 315964800;
+ struct timespec currentTime;
+ int64_t sinceBootTimeNanos;
+
+ if (getCurrentTime(currentTime, sinceBootTimeNanos) &&
+ 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_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
+ " measTimeNanos:%" PRIi64 "",
+ sinceBootTimeNanos, currentTimeNanos, measTimeNanos);
+ if (currentTimeNanos >= measTimeNanos) {
+ int64_t ageTimeNanos = currentTimeNanos - measTimeNanos;
+ LOC_LOGD("%s]: ageTimeNanos:%" PRIi64 ")", __FUNCTION__, ageTimeNanos);
+ if (ageTimeNanos >= 0 && ageTimeNanos <= sinceBootTimeNanos) {
+ 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
+ elapsedRealtime.timeUncertaintyNs = 1000000;
+ LOC_LOGd("timestampNs:%" PRIi64 ") timeUncertaintyNs:%" PRIi64 ")",
+ elapsedRealtime.timestampNs,
+ elapsedRealtime.timeUncertaintyNs);
+ }
+ }
+ } else {
+ LOC_LOGe("Failed to calculate elapsedRealtimeNanos timestamp");
+ }
+ }
}
} // namespace implementation
diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp
index c693d7b..f81a8e7 100644
--- a/gnss/GnssAdapter.cpp
+++ b/gnss/GnssAdapter.cpp
@@ -273,6 +273,11 @@
out.flags |= LOCATION_HAS_SPOOF_MASK;
out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
}
+ if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
+ out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
+ out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
+ out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
+ }
}
/* This is utility routine that computes number of SV used
diff --git a/location/LocationDataTypes.h b/location/LocationDataTypes.h
index 346a46d..febb3ff 100644
--- a/location/LocationDataTypes.h
+++ b/location/LocationDataTypes.h
@@ -75,6 +75,7 @@
LOCATION_HAS_SPEED_ACCURACY_BIT = (1<<6), // location has valid speed accuracy
LOCATION_HAS_BEARING_ACCURACY_BIT = (1<<7), // location has valid bearing accuracy
LOCATION_HAS_SPOOF_MASK = (1<<8), // location has valid spoof mask
+ LOCATION_HAS_ELAPSED_REAL_TIME = (1<<9), // location has valid elapsed real time
} LocationFlagsBits;
typedef uint16_t LocationTechnologyMask;
@@ -542,6 +543,7 @@
GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT = (1<<6),
GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT = (1<<7),
GNSS_MEASUREMENTS_CLOCK_FLAGS_HW_CLOCK_DISCONTINUITY_COUNT_BIT = (1<<8),
+ GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT = (1<<9),
} GnssMeasurementsClockFlagsBits;
typedef uint32_t GnssAidingDataSvMask;
@@ -790,6 +792,8 @@
float bearingAccuracy; // in degrees (0 to 359.999)
LocationTechnologyMask techMask;
LocationSpoofMask spoofMask;
+ uint64_t elapsedRealTime; // in ns
+ uint64_t elapsedRealTimeUnc; // in ns
} Location;
typedef enum {
@@ -1284,6 +1288,8 @@
double driftUncertaintyNsps;
uint32_t hwClockDiscontinuityCount;
GnssMeasurementsSignalType referenceSignalTypeForIsb;
+ uint64_t elapsedRealTime; // in ns
+ uint64_t elapsedRealTimeUnc; // in ns
} GnssMeasurementsClock;
typedef struct {
diff --git a/utils/loc_gps.h b/utils/loc_gps.h
index eae7383..a2a5af7 100644
--- a/utils/loc_gps.h
+++ b/utils/loc_gps.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2010, 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,6 +106,8 @@
#define LOC_GPS_LOCATION_HAS_SPEED_ACCURACY 0x0100
/** LocGpsLocation has valid bearing accuracy */
#define LOC_GPS_LOCATION_HAS_BEARING_ACCURACY 0x0200
+/** LocGpsLocation has valid Real Time and Real Time Uncertainty */
+#define LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME 0x0400
/** Spoof mask in LocGpsLocation */
typedef uint32_t LocGpsSpoofMask;
@@ -570,7 +572,11 @@
/** Represents the expected vertical uncertainity in meters*/
float vertUncertainity;
/** Timestamp for the location fix. */
- LocGpsUtcTime timestamp;
+ LocGpsUtcTime timestamp;
+ /** Elapsed RealTime in nanosends */
+ uint64_t elapsedRealTime;
+ /** Elapsed Real Time Uncertainty in nanosends */
+ uint64_t elapsedRealTimeUnc;
} LocGpsLocation;
/** Represents the status. */
diff --git a/utils/loc_misc_utils.h b/utils/loc_misc_utils.h
index 86234df..9ce4b0b 100644
--- a/utils/loc_misc_utils.h
+++ b/utils/loc_misc_utils.h
@@ -205,4 +205,25 @@
return ss.str();
}
+/*===========================================================================
+FUNCTION qTimerTicksToNanos
+
+DESCRIPTION
+ Transform from ticks to nanoseconds, clock is 19.2 MHz
+ so the formula would be qtimer(ns) = (ticks * 1000000000) / 19200000
+ or simplified qtimer(ns) = (ticks * 10000) / 192.
+
+DEPENDENCIES
+ N/A
+
+RETURN VALUE
+ Qtimer value in nanoseconds
+
+SIDE EFFECTS
+ N/A
+===========================================================================*/
+inline uint64_t qTimerTicksToNanos(double qTimer) {
+ return (uint64_t((qTimer * double(10000ull)) / (double)192ull));
+}
+
#endif //_LOC_MISC_UTILS_H_