From 2bc734afec7b8f729f19eae495b13de2dd481c40 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 3 Jan 2018 06:52:55 -0800 Subject: [PATCH] Replace message delay with send at time in playback loop. This removes the need to calculate the time needed to run the doSomeWork method. Consequently, we can use both the real Clock/Handler and the FakeClock without changing the way the playback loop works and without violating the interfaces of Clock or Handler. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=180665647 --- .../exoplayer2/ExoPlayerImplInternal.java | 6 ++- .../google/android/exoplayer2/util/Clock.java | 11 +++-- .../exoplayer2/util/HandlerWrapper.java | 14 +------ .../android/exoplayer2/util/SystemClock.java | 5 +++ .../exoplayer2/util/SystemHandlerWrapper.java | 11 +---- .../exoplayer2/testutil/FakeClock.java | 42 ++++++++++--------- 6 files changed, 40 insertions(+), 49 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 65f43ae6847..8fd508a2f0f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -117,6 +117,7 @@ private final DefaultMediaClock mediaClock; private final PlaybackInfoUpdate playbackInfoUpdate; private final ArrayList customMessageInfos; + private final Clock clock; @SuppressWarnings("unused") private SeekParameters seekParameters; @@ -159,6 +160,7 @@ public ExoPlayerImplInternal( this.shuffleModeEnabled = shuffleModeEnabled; this.eventHandler = eventHandler; this.player = player; + this.clock = clock; backBufferDurationUs = loadControl.getBackBufferDurationUs(); retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe(); @@ -541,7 +543,7 @@ private void updatePlaybackPositions() throws ExoPlaybackException { } private void doSomeWork() throws ExoPlaybackException, IOException { - long operationStartTimeMs = SystemClock.elapsedRealtime(); + long operationStartTimeMs = clock.uptimeMillis(); updatePeriods(); if (playingPeriodHolder == null) { // We're still waiting for the first period to be prepared. @@ -632,7 +634,7 @@ private void doSomeWork() throws ExoPlaybackException, IOException { private void scheduleNextWork(long thisOperationStartTimeMs, long intervalMs) { handler.removeMessages(MSG_DO_SOME_WORK); - handler.sendEmptyMessageDelayed(MSG_DO_SOME_WORK, intervalMs, thisOperationStartTimeMs); + handler.sendEmptyMessageAtTime(MSG_DO_SOME_WORK, thisOperationStartTimeMs + intervalMs); } private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException { 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 43c01bf53a9..dced6752eb5 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 @@ -30,14 +30,13 @@ public interface Clock { */ Clock DEFAULT = new SystemClock(); - /** - * @see android.os.SystemClock#elapsedRealtime() - */ + /** @see android.os.SystemClock#elapsedRealtime() */ long elapsedRealtime(); - /** - * @see android.os.SystemClock#sleep(long) - */ + /** @see android.os.SystemClock#uptimeMillis() */ + long uptimeMillis(); + + /** @see android.os.SystemClock#sleep(long) */ void sleep(long sleepTimeMs); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/HandlerWrapper.java b/library/core/src/main/java/com/google/android/exoplayer2/util/HandlerWrapper.java index b101a5e1995..3ce93f93703 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/HandlerWrapper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/HandlerWrapper.java @@ -43,18 +43,8 @@ public interface HandlerWrapper { /** @see Handler#sendEmptyMessage(int). */ boolean sendEmptyMessage(int what); - /** - * Variant of {@code Handler#sendEmptyMessageDelayed(int, long)} which also takes a reference time - * measured by {@code android.os.SystemClock#elapsedRealtime()} to which the delay is added. - * - * @param what The message identifier. - * @param delayMs The delay in milliseconds to send the message. This delay is added to the {@code - * referenceTimeMs}. - * @param referenceTimeMs The time which the delay is added to. Always measured with {@code - * android.os.SystemClock#elapsedRealtime()}. - * @return Whether the message was successfully enqueued on the Handler thread. - */ - boolean sendEmptyMessageDelayed(int what, long delayMs, long referenceTimeMs); + /** @see Handler#sendEmptyMessageAtTime(int, long). */ + boolean sendEmptyMessageAtTime(int what, long uptimeMs); /** @see Handler#removeMessages(int). */ void removeMessages(int what); 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 b24a38ea3ca..72d3df46e17 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 @@ -30,6 +30,11 @@ public long elapsedRealtime() { return android.os.SystemClock.elapsedRealtime(); } + @Override + public long uptimeMillis() { + return android.os.SystemClock.uptimeMillis(); + } + @Override public void sleep(long sleepTimeMs) { android.os.SystemClock.sleep(sleepTimeMs); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/SystemHandlerWrapper.java b/library/core/src/main/java/com/google/android/exoplayer2/util/SystemHandlerWrapper.java index aa290d9313b..ee469a5b2ad 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/SystemHandlerWrapper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/SystemHandlerWrapper.java @@ -17,7 +17,6 @@ import android.os.Looper; import android.os.Message; -import android.os.SystemClock; /** The standard implementation of {@link HandlerWrapper}. */ /* package */ final class SystemHandlerWrapper implements HandlerWrapper { @@ -59,14 +58,8 @@ public boolean sendEmptyMessage(int what) { } @Override - public boolean sendEmptyMessageDelayed(int what, long delayMs, long referenceTimeMs) { - long targetMessageTime = referenceTimeMs + delayMs; - long remainingDelayMs = targetMessageTime - SystemClock.elapsedRealtime(); - if (remainingDelayMs <= 0) { - return handler.sendEmptyMessage(what); - } else { - return handler.sendEmptyMessageDelayed(what, remainingDelayMs); - } + public boolean sendEmptyMessageAtTime(int what, long uptimeMs) { + return handler.sendEmptyMessageAtTime(what, uptimeMs); } @Override 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 index 49656eef991..a5915466133 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java @@ -67,6 +67,11 @@ public synchronized long elapsedRealtime() { return currentTimeMs; } + @Override + public long uptimeMillis() { + return elapsedRealtime(); + } + @Override public synchronized void sleep(long sleepTimeMs) { if (sleepTimeMs <= 0) { @@ -90,15 +95,23 @@ public HandlerWrapper createHandler(Looper looper, Callback callback) { } /** Adds a handler post to list of pending messages. */ - protected synchronized void addDelayedHandlerMessage( - HandlerWrapper handler, Runnable runnable, long delayMs) { - handlerMessages.add(new HandlerMessageData(currentTimeMs + delayMs, handler, runnable)); + protected synchronized boolean addHandlerMessageAtTime( + HandlerWrapper handler, Runnable runnable, long timeMs) { + if (timeMs <= currentTimeMs) { + return handler.post(runnable); + } + handlerMessages.add(new HandlerMessageData(timeMs, handler, runnable)); + return true; } /** Adds an empty handler message to list of pending messages. */ - protected synchronized void addDelayedHandlerMessage( - HandlerWrapper handler, int message, long delayMs) { - handlerMessages.add(new HandlerMessageData(currentTimeMs + delayMs, handler, message)); + protected synchronized boolean addHandlerMessageAtTime( + HandlerWrapper handler, int message, long timeMs) { + if (timeMs <= currentTimeMs) { + return handler.sendEmptyMessage(message); + } + handlerMessages.add(new HandlerMessageData(timeMs, handler, message)); + return true; } /** Message data saved to send messages or execute runnables at a later time on a Handler. */ @@ -177,14 +190,8 @@ public boolean sendEmptyMessage(int what) { } @Override - public boolean sendEmptyMessageDelayed(int what, long delayMs, long referenceTimeMs) { - // Ignore referenceTimeMs measured by SystemClock and just send with requested delay. - if (delayMs <= 0) { - return handler.sendEmptyMessage(what); - } else { - addDelayedHandlerMessage(this, what, delayMs); - return true; - } + public boolean sendEmptyMessageAtTime(int what, long uptimeMs) { + return addHandlerMessageAtTime(this, what, uptimeMs); } @Override @@ -204,12 +211,7 @@ public boolean post(Runnable runnable) { @Override public boolean postDelayed(Runnable runnable, long delayMs) { - if (delayMs <= 0) { - return handler.post(runnable); - } else { - addDelayedHandlerMessage(this, runnable, delayMs); - return true; - } + return addHandlerMessageAtTime(this, runnable, uptimeMillis() + delayMs); } } }