Snap for 4376088 from 91506df40552a4c22588632db5072da5d03b83f1 to oc-mr1-release
Change-Id: Ifd85cd5e4945cba8daa304dd5fa1547ab508741d
diff --git a/host/msm/daemon/chre_daemon.cc b/host/msm/daemon/chre_daemon.cc
index b6563b5..3c13f04 100644
--- a/host/msm/daemon/chre_daemon.cc
+++ b/host/msm/daemon/chre_daemon.cc
@@ -179,7 +179,7 @@
}
}
-static int64_t getTimeOffset() {
+static int64_t getTimeOffset(bool *success) {
int64_t timeOffset = 0;
#if defined(__aarch64__)
@@ -191,18 +191,34 @@
// Use uint64_t to store since the MRS instruction uses 64 bit (X) registers
// (http://infocenter.arm.com/help/topic/
// com.arm.doc.den0024a/ch06s05s02.html)
- uint64_t qTimerCount = 0, qTimerFreqKHz = 0;
+ uint64_t qTimerCount = 0, qTimerFreq = 0;
uint64_t hostTimeNano = elapsedRealtimeNano();
asm volatile("mrs %0, cntpct_el0" : "=r"(qTimerCount));
- asm volatile("mrs %0, cntfrq_el0" : "=r"(qTimerFreqKHz));
- qTimerFreqKHz /= 1000;
+ asm volatile("mrs %0, cntfrq_el0" : "=r"(qTimerFreq));
- if (qTimerFreqKHz != 0) {
- uint64_t qTimerNanos = (qTimerCount < UINT64_MAX / 1000000) ?
- (qTimerCount * 1000000) : UINT64_MAX;
- qTimerNanos /= qTimerFreqKHz;
+ constexpr uint64_t kOneSecondInNanoseconds = 1000000000;
+ if (qTimerFreq != 0) {
+ // Get the seconds part first, then convert the remainder to prevent
+ // overflow
+ uint64_t qTimerNanos = (qTimerCount / qTimerFreq);
+ if (qTimerNanos > UINT64_MAX / kOneSecondInNanoseconds) {
+ LOGE("CNTPCT_EL0 conversion to nanoseconds overflowed during time sync."
+ " Aborting time sync.");
+ *success = false;
+ } else {
+ qTimerNanos *= kOneSecondInNanoseconds;
- timeOffset = hostTimeNano - qTimerNanos;
+ // Round the remainder portion to the nearest nanosecond
+ uint64_t remainder = (qTimerCount % qTimerFreq);
+ qTimerNanos +=
+ (remainder * kOneSecondInNanoseconds + qTimerFreq / 2) / qTimerFreq;
+
+ timeOffset = hostTimeNano - qTimerNanos;
+ *success = true;
+ }
+ } else {
+ LOGE("CNTFRQ_EL0 had 0 value. Aborting time sync.");
+ *success = false;
}
#else
#error "Unsupported CPU architecture type"
@@ -212,16 +228,19 @@
}
static void sendTimeSyncMessage() {
- int64_t timeOffset = getTimeOffset();
+ bool timeSyncSuccess = true;
+ int64_t timeOffset = getTimeOffset(&timeSyncSuccess);
- flatbuffers::FlatBufferBuilder builder(64);
- HostProtocolHost::encodeTimeSyncMessage(builder, timeOffset);
- int success = chre_slpi_deliver_message_from_host(
- static_cast<const unsigned char *>(builder.GetBufferPointer()),
- static_cast<int>(builder.GetSize()));
+ if (timeSyncSuccess) {
+ flatbuffers::FlatBufferBuilder builder(64);
+ HostProtocolHost::encodeTimeSyncMessage(builder, timeOffset);
+ int success = chre_slpi_deliver_message_from_host(
+ static_cast<const unsigned char *>(builder.GetBufferPointer()),
+ static_cast<int>(builder.GetSize()));
- if (success != 0) {
- LOGE("Failed to deliver timestamp message from host to CHRE: %d", success);
+ if (success != 0) {
+ LOGE("Failed to deliver timestamp message from host to CHRE: %d", success);
+ }
}
}
diff --git a/platform/slpi/system_time.cc b/platform/slpi/system_time.cc
index 9ff957c..481535e 100644
--- a/platform/slpi/system_time.cc
+++ b/platform/slpi/system_time.cc
@@ -62,7 +62,19 @@
} // anonymous namespace
Nanoseconds SystemTime::getMonotonicTime() {
- return Microseconds(uTimetick_CvtFromTicks(uTimetick_Get(), T_USEC));
+ constexpr uint64_t kClockFreq = 19200000; // 19.2MHz QTimer clock
+
+ uint64_t ticks = uTimetick_Get();
+ uint64_t nsec = 0;
+ if (ticks >= kClockFreq) {
+ uint64_t seconds = (ticks / kClockFreq);
+ ticks %= kClockFreq;
+
+ nsec = (seconds * kOneSecondInNanoseconds);
+ }
+ nsec += (ticks * kOneSecondInNanoseconds) / kClockFreq;
+
+ return Nanoseconds(nsec);
}
int64_t SystemTime::getEstimatedHostTimeOffset() {