• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.util.time;
18 
19 import com.android.systemui.util.concurrency.FakeExecutor;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 
24 /**
25  * A fake {@link SystemClock} for use with {@link FakeExecutor}.
26  *
27  * Attempts to simulate the behavior of a real system clock. Time can be moved forward but not
28  * backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync.
29  *
30  * Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with
31  * every call to {@link #advanceTime}. Thread time always lags by 50% of the uptime
32  * advancement to simulate time loss due to scheduling.
33  */
34 public class FakeSystemClock implements SystemClock {
35     private long mUptimeMillis = 10000;
36     private long mElapsedRealtime = 10000;
37     private long mCurrentThreadTimeMillis = 10000;
38     private long mCurrentTimeMillis = 1555555500000L;
39     private final List<ClockTickListener> mListeners = new ArrayList<>();
40 
41     @Override
uptimeMillis()42     public long uptimeMillis() {
43         return mUptimeMillis;
44     }
45 
46     @Override
elapsedRealtime()47     public long elapsedRealtime() {
48         return mElapsedRealtime;
49     }
50 
51     @Override
elapsedRealtimeNanos()52     public long elapsedRealtimeNanos() {
53         return mElapsedRealtime * 1000000 + 447;
54     }
55 
56     @Override
currentThreadTimeMillis()57     public long currentThreadTimeMillis() {
58         return mCurrentThreadTimeMillis;
59     }
60 
61     @Override
currentTimeMillis()62     public long currentTimeMillis() {
63         return mCurrentTimeMillis;
64     }
65 
setUptimeMillis(long uptime)66     public void setUptimeMillis(long uptime) {
67         advanceTime(uptime - mUptimeMillis);
68     }
69 
setCurrentTimeMillis(long millis)70     public void setCurrentTimeMillis(long millis) {
71         mCurrentTimeMillis = millis;
72     }
73 
setElapsedRealtime(long millis)74     public void setElapsedRealtime(long millis) {
75         mElapsedRealtime = millis;
76     }
77 
78     /**
79      * Advances the time tracked by the fake clock and notifies any listeners that the time has
80      * changed (for example, an attached {@link FakeExecutor} may fire its pending runnables).
81      *
82      * All tracked times increment by [millis], with the exception of currentThreadTimeMillis,
83      * which advances by [millis] * 0.5
84      */
advanceTime(long millis)85     public void advanceTime(long millis) {
86         advanceTime(millis, 0);
87     }
88 
89     /**
90      * Advances the time tracked by the fake clock and notifies any listeners that the time has
91      * changed (for example, an attached {@link FakeExecutor} may fire its pending runnables).
92      *
93      * The tracked times change as follows:
94      * - uptimeMillis increments by [awakeMillis]
95      * - currentThreadTimeMillis increments by [awakeMillis] * 0.5
96      * - elapsedRealtime increments by [awakeMillis] + [sleepMillis]
97      * - currentTimeMillis increments by [awakeMillis] + [sleepMillis]
98      */
advanceTime(long awakeMillis, long sleepMillis)99     public void advanceTime(long awakeMillis, long sleepMillis) {
100         if (awakeMillis < 0 || sleepMillis < 0) {
101             throw new IllegalArgumentException("Time cannot go backwards");
102         }
103 
104         if (awakeMillis > 0 || sleepMillis > 0) {
105             mUptimeMillis += awakeMillis;
106             mElapsedRealtime += awakeMillis + sleepMillis;
107             mCurrentTimeMillis += awakeMillis + sleepMillis;
108 
109             mCurrentThreadTimeMillis += Math.ceil(awakeMillis * 0.5);
110 
111             for (ClockTickListener listener : mListeners) {
112                 listener.onClockTick();
113             }
114         }
115     }
116 
addListener(ClockTickListener listener)117     public void addListener(ClockTickListener listener) {
118         mListeners.add(listener);
119     }
120 
removeListener(ClockTickListener listener)121     public void removeListener(ClockTickListener listener) {
122         mListeners.remove(listener);
123     }
124 
125     public interface ClockTickListener {
onClockTick()126         void onClockTick();
127     }
128 }
129