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(