Add base::TimeTicks::FromUptimeMillis()
This allows creating a base::TimeTicks from SystemClock.uptimeMillis().
Android-only.
Also add a use this new method once instead of FromInternalValue(), which is
discouraged.
Bug: 634507, 797762
Change-Id: I8b5e3f4d0da1919f21c1f96918ca36a4e434ae0d
Reviewed-on: https://chromium-review.googlesource.com/865314
Commit-Queue: Egor Pasko <pasko@chromium.org>
Reviewed-by: Maria Khomenko <mariakhomenko@chromium.org>
Reviewed-by: Yaron Friedman <yfriedman@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531208}diff --git a/base/BUILD.gn b/base/BUILD.gn
index 379e82bf..c6e2060 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1223,6 +1223,7 @@
sources += [
"memory/shared_memory_android.cc",
"memory/shared_memory_handle_android.cc",
+ "time/time_android.cc",
]
# Android uses some Linux sources, put those back.
diff --git a/base/time/time.h b/base/time/time.h
index fd9afa2..15e20904 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -73,6 +73,10 @@
#undef TYPE_BOOL
#endif
+#if defined(OS_ANDROID)
+#include <jni.h>
+#endif
+
#if defined(OS_POSIX)
#include <unistd.h>
#include <sys/time.h>
@@ -827,6 +831,14 @@
static TimeTicks FromMachAbsoluteTime(uint64_t mach_absolute_time);
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_ANDROID)
+ // Converts to TimeTicks the value obtained from SystemClock.uptimeMillis().
+ // Note: this convertion may be non-monotonic in relation to previously
+ // obtained TimeTicks::Now() values because of the truncation (to
+ // milliseconds) performed by uptimeMillis().
+ static TimeTicks FromUptimeMillis(jlong uptime_millis_value);
+#endif
+
// Get an estimate of the TimeTick value at the time of the UnixEpoch. Because
// Time and TimeTicks respond differently to user-set time and NTP
// adjustments, this number is only an estimate. Nevertheless, this can be
diff --git a/base/time/time_android.cc b/base/time/time_android.cc
new file mode 100644
index 0000000..e0c4914
--- /dev/null
+++ b/base/time/time_android.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/time/time.h"
+
+namespace base {
+
+// static
+TimeTicks TimeTicks::FromUptimeMillis(jlong uptime_millis_value) {
+ // The implementation of the SystemClock.uptimeMillis() in AOSP uses the same
+ // clock as base::TimeTicks::Now(): clock_gettime(CLOCK_MONOTONIC), see in
+ // platform/system/code:
+ // 1. libutils/SystemClock.cpp
+ // 2. libutils/Timers.cpp
+ //
+ // We are not aware of any motivations for Android OEMs to modify the AOSP
+ // implementation of either uptimeMillis() or clock_gettime(CLOCK_MONOTONIC),
+ // so we assume that there are no such customizations.
+ //
+ // Under these assumptions the conversion is as safe as copying the value of
+ // base::TimeTicks::Now() with a loss of sub-millisecond precision.
+ return TimeTicks(uptime_millis_value * Time::kMicrosecondsPerMillisecond);
+}
+
+} // namespace base
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
index 4f73535..84d2e23 100644
--- a/base/time/time_unittest.cc
+++ b/base/time/time_unittest.cc
@@ -17,7 +17,9 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_IOS)
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#elif defined(OS_IOS)
#include "base/ios/ios_util.h"
#elif defined(OS_WIN)
#include <windows.h>
@@ -900,6 +902,28 @@
.ToInternalValue());
}
+#if defined(OS_ANDROID)
+TEST(TimeTicks, Android_FromUptimeMillis_ClocksMatch) {
+ JNIEnv* const env = android::AttachCurrentThread();
+ android::ScopedJavaLocalRef<jclass> clazz(
+ android::GetClass(env, "android/os/SystemClock"));
+ ASSERT_TRUE(clazz.obj());
+ const jmethodID method_id =
+ android::MethodID::Get<android::MethodID::TYPE_STATIC>(
+ env, clazz.obj(), "uptimeMillis", "()J");
+ ASSERT_FALSE(!method_id);
+ // Subtract 1ms from the expected lower bound to allow millisecon-level
+ // truncation performed in uptimeMillis().
+ const TimeTicks lower_bound_ticks =
+ TimeTicks::Now() - TimeDelta::FromMilliseconds(1);
+ const TimeTicks converted_ticks = TimeTicks::FromUptimeMillis(
+ env->CallStaticLongMethod(clazz.obj(), method_id));
+ const TimeTicks upper_bound_ticks = TimeTicks::Now();
+ EXPECT_LE(lower_bound_ticks, converted_ticks);
+ EXPECT_GE(upper_bound_ticks, converted_ticks);
+}
+#endif // OS_ANDROID
+
TEST(TimeDelta, FromAndIn) {
// static_assert also checks that the contained expression is a constant
// expression, meaning all its components are suitable for initializing global
diff --git a/chrome/browser/android/metrics/uma_utils.cc b/chrome/browser/android/metrics/uma_utils.cc
index 85effc8..3ea72cc 100644
--- a/chrome/browser/android/metrics/uma_utils.cc
+++ b/chrome/browser/android/metrics/uma_utils.cc
@@ -27,22 +27,8 @@
base::TimeTicks GetMainEntryPointTimeTicks() {
JNIEnv* env = base::android::AttachCurrentThread();
- // Generally the use of base::TimeTicks::FromInternalValue() is discouraged.
- //
- // The implementation of the SystemClock.uptimeMillis() in AOSP uses the same
- // clock as base::TimeTicks::Now(): clock_gettime(CLOCK_MONOTONIC), see in
- // platform/system/code:
- // 1. libutils/SystemClock.cpp
- // 2. libutils/Timers.cpp
- //
- // We are not aware of any motivations for Android OEMs to modify the AOSP
- // implementation of either uptimeMillis() or clock_gettime(CLOCK_MONOTONIC),
- // so we assume that there are no such customizations.
- //
- // Under these assumptions the conversion is as safe as copying the value of
- // base::TimeTicks::Now() with a loss of sub-millisecond precision.
- return base::TimeTicks::FromInternalValue(
- Java_UmaUtils_getMainEntryPointTicks(env) * 1000);
+ return base::TimeTicks::FromUptimeMillis(
+ Java_UmaUtils_getMainEntryPointTicks(env));
}
static jboolean JNI_UmaUtils_IsClientInMetricsReportingSample(