diff --git a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java index 0a6fa9e6b1..204a2756bb 100644 --- a/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java +++ b/extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java @@ -28,7 +28,6 @@ import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Predicate; -import com.google.android.exoplayer2.util.SystemClock; import java.io.IOException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; @@ -169,7 +168,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou int connectTimeoutMs, int readTimeoutMs, boolean resetTimeoutOnRedirects, RequestProperties defaultRequestProperties) { this(cronetEngine, executor, contentTypePredicate, listener, connectTimeoutMs, - readTimeoutMs, resetTimeoutOnRedirects, new SystemClock(), defaultRequestProperties); + readTimeoutMs, resetTimeoutOnRedirects, Clock.DEFAULT, defaultRequestProperties); } /* package */ CronetDataSource(CronetEngine cronetEngine, Executor executor, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Clock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Clock.java index 01f667ed86..044d87d0a4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Clock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Clock.java @@ -16,16 +16,24 @@ package com.google.android.exoplayer2.util; /** - * An interface through which system clocks can be read. The {@link SystemClock} implementation + * An interface through which system clocks can be read. The {@link #DEFAULT} implementation * must be used for all non-test cases. */ public interface Clock { /** - * Returns {@link android.os.SystemClock#elapsedRealtime}. - * - * @return Elapsed milliseconds since boot. + * Default {@link Clock} to use for all non-test cases. + */ + Clock DEFAULT = new SystemClock(); + + /** + * @see android.os.SystemClock#elapsedRealtime(). */ long elapsedRealtime(); + /** + * @see android.os.SystemClock#sleep(long). + */ + void sleep(long sleepTimeMs); + } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/SystemClock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/SystemClock.java index b05675f647..1f937b721b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/SystemClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/SystemClock.java @@ -18,11 +18,16 @@ package com.google.android.exoplayer2.util; /** * The standard implementation of {@link Clock}. */ -public final class SystemClock implements Clock { +/* package */ final class SystemClock implements Clock { @Override public long elapsedRealtime() { return android.os.SystemClock.elapsedRealtime(); } + @Override + public void sleep(long sleepTimeMs) { + android.os.SystemClock.sleep(sleepTimeMs); + } + } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java new file mode 100644 index 0000000000..36ce4b5c3e --- /dev/null +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.testutil; + +import com.google.android.exoplayer2.util.Clock; +import java.util.ArrayList; +import java.util.List; + +/** + * Fake {@link Clock} implementation independent of {@link android.os.SystemClock}. + */ +public final class FakeClock implements Clock { + + private long currentTimeMs; + private final List wakeUpTimes; + + /** + * Create {@link FakeClock} with an arbitrary initial timestamp. + * + * @param initialTimeMs Initial timestamp in milliseconds. + */ + public FakeClock(long initialTimeMs) { + this.currentTimeMs = initialTimeMs; + this.wakeUpTimes = new ArrayList<>(); + } + + /** + * Advance timestamp of {@link FakeClock} by the specified duration. + * + * @param timeDiffMs The amount of time to add to the timestamp in milliseconds. + */ + public synchronized void advanceTime(long timeDiffMs) { + currentTimeMs += timeDiffMs; + for (Long wakeUpTime : wakeUpTimes) { + if (wakeUpTime <= currentTimeMs) { + notifyAll(); + break; + } + } + } + + @Override + public long elapsedRealtime() { + return currentTimeMs; + } + + @Override + public synchronized void sleep(long sleepTimeMs) { + if (sleepTimeMs <= 0) { + return; + } + Long wakeUpTimeMs = currentTimeMs + sleepTimeMs; + wakeUpTimes.add(wakeUpTimeMs); + while (currentTimeMs < wakeUpTimeMs) { + try { + wait(); + } catch (InterruptedException e) { + // Ignore InterruptedException as SystemClock.sleep does too. + } + } + wakeUpTimes.remove(wakeUpTimeMs); + } + +} +