1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 import android.os.SystemClock; 8 9 import org.chromium.build.annotations.CheckDiscard; 10 11 /** 12 * Utilities related to timestamps, including the ability to use fake time for tests via 13 * FakeTimeTestRule. 14 */ 15 public class TimeUtils { 16 /** 17 * Interval timer using SystemClock.uptimeMillis() (excludes deep sleep). 18 * See: https://developer.android.com/reference/android/os/SystemClock 19 */ 20 @CheckDiscard("Class should get inlined by R8.") 21 public static class UptimeMillisTimer { 22 private final long mStart = uptimeMillis(); 23 getElapsedMillis()24 public long getElapsedMillis() { 25 return uptimeMillis() - mStart; 26 } 27 } 28 29 /** 30 * Interval timer using SystemClock.elapsedRealtime() (includes deep sleep). 31 * See: https://developer.android.com/reference/android/os/SystemClock 32 */ 33 @CheckDiscard("Class should get inlined by R8.") 34 public static class ElapsedRealtimeMillisTimer { 35 private final long mStart = elapsedRealtimeMillis(); 36 getElapsedMillis()37 public long getElapsedMillis() { 38 return elapsedRealtimeMillis() - mStart; 39 } 40 } 41 42 /** 43 * Interval timer using SystemClock.elapsedRealtimeNanos() (includes deep sleep). 44 * See: https://developer.android.com/reference/android/os/SystemClock 45 */ 46 @CheckDiscard("Class should get inlined by R8.") 47 public static class ElapsedRealtimeNanosTimer { 48 private final long mStart = elapsedRealtimeNanos(); 49 getElapsedNanos()50 public long getElapsedNanos() { 51 return elapsedRealtimeNanos() - mStart; 52 } 53 } 54 55 /** 56 * Interval timer using SystemClock.currentThreadTimeMillis() (excludes blocking time). 57 * See: https://developer.android.com/reference/android/os/SystemClock 58 */ 59 @CheckDiscard("Class should get inlined by R8.") 60 public static class CurrentThreadTimeMillisTimer { 61 private final long mStart = currentThreadTimeMillis(); 62 getElapsedMillis()63 public long getElapsedMillis() { 64 return currentThreadTimeMillis() - mStart; 65 } 66 } 67 68 interface FakeClock { uptimeMillis()69 long uptimeMillis(); 70 elapsedRealtimeNanos()71 long elapsedRealtimeNanos(); 72 currentThreadTimeMillis()73 long currentThreadTimeMillis(); 74 currentTimeMillis()75 long currentTimeMillis(); 76 } 77 TimeUtils()78 private TimeUtils() {} 79 80 // Use these in favor of TimeUnit.convert() in order to avoid the overhead of a 81 // static-get / static-invoke. 82 public static final long SECONDS_PER_MINUTE = 60; 83 public static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60; 84 public static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24; 85 public static final long MILLISECONDS_PER_MINUTE = SECONDS_PER_MINUTE * 1000; 86 public static final long NANOSECONDS_PER_MICROSECOND = 1000; 87 public static final long NANOSECONDS_PER_MILLISECOND = 1000000; 88 89 // Used by FakeTimeTestRule. Visibility is restricted to ensure tests use the rule, which 90 // restores the value to null in its clean-up logic. 91 static FakeClock sFakeClock; 92 93 /** 94 * Wrapper for System.currentTimeMillis() (milliseconds since the epoch). 95 * Can be faked in tests using FakeTimeTestRule. 96 * See: https://developer.android.com/reference/android/os/SystemClock 97 */ 98 @CheckDiscard("Should get inlined by R8.") currentTimeMillis()99 public static long currentTimeMillis() { 100 if (sFakeClock != null) { 101 return sFakeClock.currentTimeMillis(); 102 } 103 return System.currentTimeMillis(); 104 } 105 106 /** 107 * Wrapper for SystemClock.uptimeMillis() (uptime excluding deep sleep). 108 * Can be faked in tests using FakeTimeTestRule. 109 * See: https://developer.android.com/reference/android/os/SystemClock 110 */ 111 @CheckDiscard("Should get inlined by R8.") uptimeMillis()112 public static long uptimeMillis() { 113 if (sFakeClock != null) { 114 return sFakeClock.uptimeMillis(); 115 } 116 return SystemClock.uptimeMillis(); 117 } 118 119 /** 120 * Wrapper for SystemClock.elapsedRealtimeNanos() (uptime including deep sleep). 121 * Can be faked in tests using FakeTimeTestRule. 122 * See: https://developer.android.com/reference/android/os/SystemClock 123 */ 124 @CheckDiscard("Should get inlined by R8.") elapsedRealtimeNanos()125 public static long elapsedRealtimeNanos() { 126 if (sFakeClock != null) { 127 return sFakeClock.elapsedRealtimeNanos(); 128 } 129 return SystemClock.elapsedRealtimeNanos(); 130 } 131 132 /** 133 * Wrapper for SystemClock.elapsedRealtimeMillis() (uptime including deep sleep). 134 * Can be faked in tests using FakeTimeTestRule. 135 * See: https://developer.android.com/reference/android/os/SystemClock 136 */ 137 @CheckDiscard("Should get inlined by R8.") elapsedRealtimeMillis()138 public static long elapsedRealtimeMillis() { 139 if (sFakeClock != null) { 140 return sFakeClock.elapsedRealtimeNanos() / NANOSECONDS_PER_MILLISECOND; 141 } 142 return SystemClock.elapsedRealtime(); 143 } 144 145 /** 146 * Wrapper for SystemClock.currentThreadTimeMillis() (excludes blocking time). 147 * Can be faked in tests using FakeTimeTestRule. 148 * See: https://developer.android.com/reference/android/os/SystemClock 149 */ 150 @CheckDiscard("Should get inlined by R8.") currentThreadTimeMillis()151 public static long currentThreadTimeMillis() { 152 if (sFakeClock != null) { 153 return sFakeClock.currentThreadTimeMillis(); 154 } 155 return SystemClock.currentThreadTimeMillis(); 156 } 157 } 158