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