// Copyright 2016 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.base; import android.os.SystemClock; import org.chromium.build.annotations.CheckDiscard; /** * Utilities related to timestamps, including the ability to use fake time for tests via * FakeTimeTestRule. */ public class TimeUtils { /** * Interval timer using SystemClock.uptimeMillis() (excludes deep sleep). * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Class should get inlined by R8.") public static class UptimeMillisTimer { private final long mStart = uptimeMillis(); public long getElapsedMillis() { return uptimeMillis() - mStart; } } /** * Interval timer using SystemClock.elapsedRealtime() (includes deep sleep). * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Class should get inlined by R8.") public static class ElapsedRealtimeMillisTimer { private final long mStart = elapsedRealtimeMillis(); public long getElapsedMillis() { return elapsedRealtimeMillis() - mStart; } } /** * Interval timer using SystemClock.elapsedRealtimeNanos() (includes deep sleep). * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Class should get inlined by R8.") public static class ElapsedRealtimeNanosTimer { private final long mStart = elapsedRealtimeNanos(); public long getElapsedNanos() { return elapsedRealtimeNanos() - mStart; } } /** * Interval timer using SystemClock.currentThreadTimeMillis() (excludes blocking time). * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Class should get inlined by R8.") public static class CurrentThreadTimeMillisTimer { private final long mStart = currentThreadTimeMillis(); public long getElapsedMillis() { return currentThreadTimeMillis() - mStart; } } interface FakeClock { long uptimeMillis(); long elapsedRealtimeNanos(); long currentThreadTimeMillis(); long currentTimeMillis(); } private TimeUtils() {} // Use these in favor of TimeUnit.convert() in order to avoid the overhead of a // static-get / static-invoke. public static final long SECONDS_PER_MINUTE = 60; public static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60; public static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24; public static final long MILLISECONDS_PER_MINUTE = SECONDS_PER_MINUTE * 1000; public static final long NANOSECONDS_PER_MICROSECOND = 1000; public static final long NANOSECONDS_PER_MILLISECOND = 1000000; // Used by FakeTimeTestRule. Visibility is restricted to ensure tests use the rule, which // restores the value to null in its clean-up logic. static FakeClock sFakeClock; /** * Wrapper for System.currentTimeMillis() (milliseconds since the epoch). * Can be faked in tests using FakeTimeTestRule. * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Should get inlined by R8.") public static long currentTimeMillis() { if (sFakeClock != null) { return sFakeClock.currentTimeMillis(); } return System.currentTimeMillis(); } /** * Wrapper for SystemClock.uptimeMillis() (uptime excluding deep sleep). * Can be faked in tests using FakeTimeTestRule. * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Should get inlined by R8.") public static long uptimeMillis() { if (sFakeClock != null) { return sFakeClock.uptimeMillis(); } return SystemClock.uptimeMillis(); } /** * Wrapper for SystemClock.elapsedRealtimeNanos() (uptime including deep sleep). * Can be faked in tests using FakeTimeTestRule. * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Should get inlined by R8.") public static long elapsedRealtimeNanos() { if (sFakeClock != null) { return sFakeClock.elapsedRealtimeNanos(); } return SystemClock.elapsedRealtimeNanos(); } /** * Wrapper for SystemClock.elapsedRealtimeMillis() (uptime including deep sleep). * Can be faked in tests using FakeTimeTestRule. * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Should get inlined by R8.") public static long elapsedRealtimeMillis() { if (sFakeClock != null) { return sFakeClock.elapsedRealtimeNanos() / NANOSECONDS_PER_MILLISECOND; } return SystemClock.elapsedRealtime(); } /** * Wrapper for SystemClock.currentThreadTimeMillis() (excludes blocking time). * Can be faked in tests using FakeTimeTestRule. * See: https://developer.android.com/reference/android/os/SystemClock */ @CheckDiscard("Should get inlined by R8.") public static long currentThreadTimeMillis() { if (sFakeClock != null) { return sFakeClock.currentThreadTimeMillis(); } return SystemClock.currentThreadTimeMillis(); } }