mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Fix FakeClock remove messages behaviour.
We currently only remove messages that have already been sent to the actual Handler, not the pending ones that are only kept in the FakeClock. Fix this by also removing matching messages from the FakeClock list. PiperOrigin-RevId: 353877049
This commit is contained in:
parent
89ea38d155
commit
a318e56d15
@ -108,6 +108,27 @@ public class FakeClock implements Clock {
|
||||
maybeTriggerMessages();
|
||||
}
|
||||
|
||||
private synchronized void removePendingHandlerMessages(ClockHandler handler, int what) {
|
||||
for (int i = handlerMessages.size() - 1; i >= 0; i--) {
|
||||
HandlerMessage message = handlerMessages.get(i);
|
||||
if (message.handler.equals(handler) && message.what == what) {
|
||||
handlerMessages.remove(i);
|
||||
}
|
||||
}
|
||||
handler.handler.removeMessages(what);
|
||||
}
|
||||
|
||||
private synchronized void removePendingHandlerMessages(
|
||||
ClockHandler handler, @Nullable Object token) {
|
||||
for (int i = handlerMessages.size() - 1; i >= 0; i--) {
|
||||
HandlerMessage message = handlerMessages.get(i);
|
||||
if (message.handler.equals(handler) && (token == null || message.obj == token)) {
|
||||
handlerMessages.remove(i);
|
||||
}
|
||||
}
|
||||
handler.handler.removeCallbacksAndMessages(token);
|
||||
}
|
||||
|
||||
private synchronized boolean hasPendingMessage(ClockHandler handler, int what) {
|
||||
for (int i = 0; i < handlerMessages.size(); i++) {
|
||||
HandlerMessage message = handlerMessages.get(i);
|
||||
@ -261,12 +282,12 @@ public class FakeClock implements Clock {
|
||||
|
||||
@Override
|
||||
public void removeMessages(int what) {
|
||||
handler.removeMessages(what);
|
||||
removePendingHandlerMessages(/* handler= */ this, what);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCallbacksAndMessages(@Nullable Object token) {
|
||||
handler.removeCallbacksAndMessages(token);
|
||||
removePendingHandlerMessages(/* handler= */ this, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
@ -186,6 +187,87 @@ public final class FakeClockTest {
|
||||
assertTestRunnableStates(new boolean[] {true, true, true, true, true}, testRunnables);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createHandler_removeMessages_removesMessages() {
|
||||
HandlerThread handlerThread = new HandlerThread("FakeClockTest");
|
||||
handlerThread.start();
|
||||
FakeClock fakeClock = new FakeClock(/* initialTimeMs= */ 0);
|
||||
TestCallback callback = new TestCallback();
|
||||
HandlerWrapper handler = fakeClock.createHandler(handlerThread.getLooper(), callback);
|
||||
TestCallback otherCallback = new TestCallback();
|
||||
HandlerWrapper otherHandler = fakeClock.createHandler(handlerThread.getLooper(), otherCallback);
|
||||
|
||||
// Block any further execution on the HandlerThread until we had a chance to remove messages.
|
||||
ConditionVariable startCondition = new ConditionVariable();
|
||||
handler.post(startCondition::block);
|
||||
TestRunnable testRunnable1 = new TestRunnable();
|
||||
TestRunnable testRunnable2 = new TestRunnable();
|
||||
Object messageToken = new Object();
|
||||
handler.obtainMessage(/* what= */ 1, /* obj= */ messageToken).sendToTarget();
|
||||
handler.sendEmptyMessageDelayed(/* what= */ 2, /* delayMs= */ 50);
|
||||
handler.post(testRunnable1);
|
||||
handler.postDelayed(testRunnable2, /* delayMs= */ 25);
|
||||
handler.sendEmptyMessage(/* what= */ 3);
|
||||
otherHandler.sendEmptyMessage(/* what= */ 2);
|
||||
|
||||
handler.removeMessages(/* what= */ 2);
|
||||
handler.removeCallbacksAndMessages(messageToken);
|
||||
|
||||
startCondition.open();
|
||||
fakeClock.advanceTime(50);
|
||||
shadowOf(handlerThread.getLooper()).idle();
|
||||
|
||||
assertThat(callback.messages)
|
||||
.containsExactly(
|
||||
new MessageData(/* what= */ 3, /* arg1= */ 0, /* arg2= */ 0, /* obj=*/ null));
|
||||
assertThat(testRunnable1.hasRun).isTrue();
|
||||
assertThat(testRunnable2.hasRun).isTrue();
|
||||
|
||||
// Assert that message with same "what" on other handler wasn't removed.
|
||||
assertThat(otherCallback.messages)
|
||||
.containsExactly(
|
||||
new MessageData(/* what= */ 2, /* arg1= */ 0, /* arg2= */ 0, /* obj=*/ null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createHandler_removeAllMessages_removesAllMessages() {
|
||||
HandlerThread handlerThread = new HandlerThread("FakeClockTest");
|
||||
handlerThread.start();
|
||||
FakeClock fakeClock = new FakeClock(/* initialTimeMs= */ 0);
|
||||
TestCallback callback = new TestCallback();
|
||||
HandlerWrapper handler = fakeClock.createHandler(handlerThread.getLooper(), callback);
|
||||
TestCallback otherCallback = new TestCallback();
|
||||
HandlerWrapper otherHandler = fakeClock.createHandler(handlerThread.getLooper(), otherCallback);
|
||||
|
||||
// Block any further execution on the HandlerThread until we had a chance to remove messages.
|
||||
ConditionVariable startCondition = new ConditionVariable();
|
||||
handler.post(startCondition::block);
|
||||
TestRunnable testRunnable1 = new TestRunnable();
|
||||
TestRunnable testRunnable2 = new TestRunnable();
|
||||
Object messageToken = new Object();
|
||||
handler.obtainMessage(/* what= */ 1, /* obj= */ messageToken).sendToTarget();
|
||||
handler.sendEmptyMessageDelayed(/* what= */ 2, /* delayMs= */ 50);
|
||||
handler.post(testRunnable1);
|
||||
handler.postDelayed(testRunnable2, /* delayMs= */ 25);
|
||||
handler.sendEmptyMessage(/* what= */ 3);
|
||||
otherHandler.sendEmptyMessage(/* what= */ 1);
|
||||
|
||||
handler.removeCallbacksAndMessages(/* token= */ null);
|
||||
|
||||
startCondition.open();
|
||||
fakeClock.advanceTime(50);
|
||||
shadowOf(handlerThread.getLooper()).idle();
|
||||
|
||||
assertThat(callback.messages).isEmpty();
|
||||
assertThat(testRunnable1.hasRun).isFalse();
|
||||
assertThat(testRunnable2.hasRun).isFalse();
|
||||
|
||||
// Assert that message on other handler wasn't removed.
|
||||
assertThat(otherCallback.messages)
|
||||
.containsExactly(
|
||||
new MessageData(/* what= */ 1, /* arg1= */ 0, /* arg2= */ 0, /* obj=*/ null));
|
||||
}
|
||||
|
||||
private static void assertTestRunnableStates(boolean[] states, TestRunnable[] testRunnables) {
|
||||
for (int i = 0; i < testRunnables.length; i++) {
|
||||
assertThat(testRunnables[i].hasRun).isEqualTo(states[i]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user