31
31
import com .google .common .collect .ComparisonChain ;
32
32
import com .google .common .collect .ImmutableSet ;
33
33
import com .google .common .collect .Ordering ;
34
+ import com .google .errorprone .annotations .CanIgnoreReturnValue ;
34
35
import java .util .ArrayList ;
35
36
import java .util .Collections ;
36
37
import java .util .HashSet ;
55
56
@ UnstableApi
56
57
public class FakeClock implements Clock {
57
58
59
+ /** A builder for {@link FakeClock} instances. */
60
+ public static final class Builder {
61
+ private long bootTimeMs ;
62
+ private long initialTimeMs ;
63
+ private boolean isAutoAdvancing ;
64
+ private long maxAutoAdvancingTimeDiffMs ;
65
+
66
+ /** Creates a new builder for {@link FakeClock} instances. */
67
+ public Builder () {
68
+ bootTimeMs = 0 ;
69
+ initialTimeMs = 0 ;
70
+ isAutoAdvancing = false ;
71
+ maxAutoAdvancingTimeDiffMs = DEFAULT_MAX_AUTO_ADVANCING_TIME_DIFF_MS ;
72
+ }
73
+
74
+ /**
75
+ * Sets the time the system was booted since the Unix Epoch, in milliseconds.
76
+ *
77
+ * <p>The default value is 0.
78
+ *
79
+ * @param bootTimeMs The time the system was booted since the Unix Epoch, in milliseconds.
80
+ * @return This builder.
81
+ */
82
+ @ CanIgnoreReturnValue
83
+ public Builder setBootTimeMs (long bootTimeMs ) {
84
+ this .bootTimeMs = bootTimeMs ;
85
+ return this ;
86
+ }
87
+
88
+ /**
89
+ * Sets the initial elapsed time since the boot time, in milliseconds.
90
+ *
91
+ * <p>The default value is 0.
92
+ *
93
+ * @param initialTimeMs The initial elapsed time since the boot time, in milliseconds.
94
+ * @return This builder.
95
+ */
96
+ @ CanIgnoreReturnValue
97
+ public Builder setInitialTimeMs (long initialTimeMs ) {
98
+ this .initialTimeMs = initialTimeMs ;
99
+ return this ;
100
+ }
101
+
102
+ /**
103
+ * Sets whether the clock should automatically advance the time to the time of the next message
104
+ * that is due to be sent.
105
+ *
106
+ * <p>The default value is false.
107
+ *
108
+ * @param isAutoAdvancing Whether the clock should automatically advance the time.
109
+ * @return This builder.
110
+ */
111
+ @ CanIgnoreReturnValue
112
+ public Builder setIsAutoAdvancing (boolean isAutoAdvancing ) {
113
+ this .isAutoAdvancing = isAutoAdvancing ;
114
+ return this ;
115
+ }
116
+
117
+ /**
118
+ * Sets the maximum time difference between two messages that the fake clock will automatically
119
+ * advance.
120
+ *
121
+ * <p>The default value is {@link #DEFAULT_MAX_AUTO_ADVANCING_TIME_DIFF_MS}.
122
+ *
123
+ * @param maxAutoAdvancingTimeDiffMs The maximum time difference in milliseconds.
124
+ * @return This builder.
125
+ */
126
+ @ CanIgnoreReturnValue
127
+ public Builder setMaxAutoAdvancingTimeDiffMs (long maxAutoAdvancingTimeDiffMs ) {
128
+ this .maxAutoAdvancingTimeDiffMs = maxAutoAdvancingTimeDiffMs ;
129
+ return this ;
130
+ }
131
+
132
+ /**
133
+ * Builds a {@link FakeClock} instance.
134
+ *
135
+ * @return The built {@link FakeClock} instance.
136
+ */
137
+ public FakeClock build () {
138
+ return new FakeClock (/* builder= */ this );
139
+ }
140
+ }
141
+
142
+ /**
143
+ * The default maximum time difference between two messages that the fake clock will automatically
144
+ * advance.
145
+ */
146
+ public static final long DEFAULT_MAX_AUTO_ADVANCING_TIME_DIFF_MS = 1000 ;
147
+
58
148
private static final ImmutableSet <String > UI_INTERACTION_TEST_CLASSES =
59
149
ImmutableSet .of (
60
150
"org.robolectric.android.internal.LocalControlledLooper" ,
@@ -69,6 +159,7 @@ public class FakeClock implements Clock {
69
159
private final boolean isRobolectric ;
70
160
private final boolean isAutoAdvancing ;
71
161
private final Handler mainHandler ;
162
+ private final long maxAutoAdvancingTimeDiffMs ;
72
163
73
164
@ GuardedBy ("this" )
74
165
private final List <HandlerMessage > handlerMessages ;
@@ -129,15 +220,24 @@ public FakeClock(long initialTimeMs, boolean isAutoAdvancing) {
129
220
* next message that is due to be sent.
130
221
*/
131
222
public FakeClock (long bootTimeMs , long initialTimeMs , boolean isAutoAdvancing ) {
132
- this .bootTimeMs = bootTimeMs ;
133
- this .timeSinceBootMs = initialTimeMs ;
134
- this .isAutoAdvancing = isAutoAdvancing ;
223
+ this (
224
+ new Builder ()
225
+ .setBootTimeMs (bootTimeMs )
226
+ .setInitialTimeMs (initialTimeMs )
227
+ .setIsAutoAdvancing (isAutoAdvancing ));
228
+ }
229
+
230
+ private FakeClock (Builder builder ) {
231
+ this .bootTimeMs = builder .bootTimeMs ;
232
+ this .timeSinceBootMs = builder .initialTimeMs ;
233
+ this .isAutoAdvancing = builder .isAutoAdvancing ;
234
+ this .maxAutoAdvancingTimeDiffMs = builder .maxAutoAdvancingTimeDiffMs ;
135
235
this .handlerMessages = new ArrayList <>();
136
236
this .busyLoopers = new HashSet <>();
137
237
this .mainHandler = new Handler (Looper .getMainLooper ());
138
238
this .isRobolectric = "robolectric" .equals (Build .FINGERPRINT );
139
239
if (isRobolectric ) {
140
- SystemClock .setCurrentTimeMillis (initialTimeMs );
240
+ SystemClock .setCurrentTimeMillis (builder . initialTimeMs );
141
241
}
142
242
}
143
243
@@ -271,8 +371,9 @@ private synchronized void maybeTriggerMessage() {
271
371
return ;
272
372
}
273
373
if (message .timeMs > timeSinceBootMs ) {
274
- if (isAutoAdvancing ) {
275
- advanceTimeInternal (message .timeMs - timeSinceBootMs );
374
+ long timeDiff = message .timeMs - timeSinceBootMs ;
375
+ if (isAutoAdvancing && timeDiff <= maxAutoAdvancingTimeDiffMs ) {
376
+ advanceTimeInternal (timeDiff );
276
377
} else {
277
378
return ;
278
379
}
0 commit comments