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_