mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Fix bug where BasePreloadManager.Listener invokes from incorrect thread
The DefaultPreloadManagerTest didn't to catch this because we use main looper as the preload looper in the tests. This CL also improves the tests by assigning the preload looper with one that corresponds to a different thread. PiperOrigin-RevId: 655664189
This commit is contained in:
parent
4fc66f42d6
commit
edd3a3f349
@ -72,13 +72,12 @@ public abstract class BasePreloadManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Object lock;
|
private final Object lock;
|
||||||
private final Looper looper;
|
|
||||||
protected final Comparator<T> rankingDataComparator;
|
protected final Comparator<T> rankingDataComparator;
|
||||||
private final TargetPreloadStatusControl<T> targetPreloadStatusControl;
|
private final TargetPreloadStatusControl<T> targetPreloadStatusControl;
|
||||||
private final MediaSource.Factory mediaSourceFactory;
|
private final MediaSource.Factory mediaSourceFactory;
|
||||||
private final ListenerSet<Listener> listeners;
|
private final ListenerSet<Listener> listeners;
|
||||||
private final Map<MediaItem, MediaSourceHolder> mediaItemMediaSourceHolderMap;
|
private final Map<MediaItem, MediaSourceHolder> mediaItemMediaSourceHolderMap;
|
||||||
private final Handler startPreloadingHandler;
|
private final Handler applicationHandler;
|
||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final PriorityQueue<MediaSourceHolder> sourceHolderPriorityQueue;
|
private final PriorityQueue<MediaSourceHolder> sourceHolderPriorityQueue;
|
||||||
@ -92,13 +91,13 @@ public abstract class BasePreloadManager<T> {
|
|||||||
TargetPreloadStatusControl<T> targetPreloadStatusControl,
|
TargetPreloadStatusControl<T> targetPreloadStatusControl,
|
||||||
MediaSource.Factory mediaSourceFactory) {
|
MediaSource.Factory mediaSourceFactory) {
|
||||||
lock = new Object();
|
lock = new Object();
|
||||||
looper = Util.getCurrentOrMainLooper();
|
applicationHandler = Util.createHandlerForCurrentOrMainLooper();
|
||||||
this.rankingDataComparator = rankingDataComparator;
|
this.rankingDataComparator = rankingDataComparator;
|
||||||
this.targetPreloadStatusControl = targetPreloadStatusControl;
|
this.targetPreloadStatusControl = targetPreloadStatusControl;
|
||||||
this.mediaSourceFactory = mediaSourceFactory;
|
this.mediaSourceFactory = mediaSourceFactory;
|
||||||
listeners = new ListenerSet<>(looper, Clock.DEFAULT, (listener, flags) -> {});
|
listeners =
|
||||||
|
new ListenerSet<>(applicationHandler.getLooper(), Clock.DEFAULT, (listener, flags) -> {});
|
||||||
mediaItemMediaSourceHolderMap = new HashMap<>();
|
mediaItemMediaSourceHolderMap = new HashMap<>();
|
||||||
startPreloadingHandler = Util.createHandlerForCurrentOrMainLooper();
|
|
||||||
sourceHolderPriorityQueue = new PriorityQueue<>();
|
sourceHolderPriorityQueue = new PriorityQueue<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,35 +256,39 @@ public abstract class BasePreloadManager<T> {
|
|||||||
|
|
||||||
/** Called when the given {@link MediaSource} completes preloading. */
|
/** Called when the given {@link MediaSource} completes preloading. */
|
||||||
protected final void onPreloadCompleted(MediaSource source) {
|
protected final void onPreloadCompleted(MediaSource source) {
|
||||||
listeners.sendEvent(
|
applicationHandler.post(
|
||||||
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onCompleted(source.getMediaItem()));
|
() -> {
|
||||||
maybeAdvanceToNextSource(source);
|
listeners.sendEvent(
|
||||||
|
/* eventFlag= */ C.INDEX_UNSET,
|
||||||
|
listener -> listener.onCompleted(source.getMediaItem()));
|
||||||
|
maybeAdvanceToNextSource(source);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when an error occurs. */
|
/** Called when an error occurs. */
|
||||||
protected final void onPreloadError(PreloadException error, MediaSource source) {
|
protected final void onPreloadError(PreloadException error, MediaSource source) {
|
||||||
listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onError(error));
|
applicationHandler.post(
|
||||||
maybeAdvanceToNextSource(source);
|
() -> {
|
||||||
|
listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onError(error));
|
||||||
|
maybeAdvanceToNextSource(source);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when the given {@link MediaSource} has been skipped before completing preloading. */
|
/** Called when the given {@link MediaSource} has been skipped before completing preloading. */
|
||||||
protected final void onPreloadSkipped(MediaSource source) {
|
protected final void onPreloadSkipped(MediaSource source) {
|
||||||
maybeAdvanceToNextSource(source);
|
applicationHandler.post(() -> maybeAdvanceToNextSource(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeAdvanceToNextSource(MediaSource preloadingSource) {
|
private void maybeAdvanceToNextSource(MediaSource preloadingSource) {
|
||||||
startPreloadingHandler.post(
|
synchronized (lock) {
|
||||||
() -> {
|
if (sourceHolderPriorityQueue.isEmpty()
|
||||||
synchronized (lock) {
|
|| checkNotNull(sourceHolderPriorityQueue.peek()).mediaSource != preloadingSource) {
|
||||||
if (sourceHolderPriorityQueue.isEmpty()
|
return;
|
||||||
|| checkNotNull(sourceHolderPriorityQueue.peek()).mediaSource != preloadingSource) {
|
}
|
||||||
return;
|
do {
|
||||||
}
|
sourceHolderPriorityQueue.poll();
|
||||||
do {
|
} while (!sourceHolderPriorityQueue.isEmpty() && !maybeStartPreloadNextSource());
|
||||||
sourceHolderPriorityQueue.poll();
|
}
|
||||||
} while (!sourceHolderPriorityQueue.isEmpty() && !maybeStartPreloadNextSource());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -372,7 +375,7 @@ public abstract class BasePreloadManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void verifyApplicationThread() {
|
private void verifyApplicationThread() {
|
||||||
if (Looper.myLooper() != looper) {
|
if (Looper.myLooper() != applicationHandler.getLooper()) {
|
||||||
throw new IllegalStateException("Preload manager is accessed on the wrong thread.");
|
throw new IllegalStateException("Preload manager is accessed on the wrong thread.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import static org.robolectric.Shadows.shadowOf;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.HandlerThread;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.AdPlaybackState;
|
import androidx.media3.common.AdPlaybackState;
|
||||||
@ -186,7 +187,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_withoutSettingCurrentPlayingIndex_sourcesPreloadedToTargetStatusesInOrder()
|
public void invalidate_withoutSettingCurrentPlayingIndex_sourcesPreloadedToTargetStatusInOrder()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
AtomicInteger currentPlayingItemIndex = new AtomicInteger();
|
AtomicInteger currentPlayingItemIndex = new AtomicInteger();
|
||||||
@ -202,6 +203,8 @@ public class DefaultPreloadManagerTest {
|
|||||||
ProgressiveMediaSource.Factory mediaSourceFactory =
|
ProgressiveMediaSource.Factory mediaSourceFactory =
|
||||||
new ProgressiveMediaSource.Factory(
|
new ProgressiveMediaSource.Factory(
|
||||||
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -210,7 +213,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
||||||
@ -240,10 +243,12 @@ public class DefaultPreloadManagerTest {
|
|||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
||||||
.containsExactly(mediaItem0, mediaItem1, mediaItem2)
|
.containsExactly(mediaItem0, mediaItem1, mediaItem2)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_withSettingCurrentPlayingIndex_sourcesPreloadedToTargetStatusesInOrder()
|
public void invalidate_withSettingCurrentPlayingIndex_sourcesPreloadedToTargetStatusInOrder()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
AtomicInteger currentPlayingItemIndex = new AtomicInteger();
|
AtomicInteger currentPlayingItemIndex = new AtomicInteger();
|
||||||
@ -259,6 +264,8 @@ public class DefaultPreloadManagerTest {
|
|||||||
ProgressiveMediaSource.Factory mediaSourceFactory =
|
ProgressiveMediaSource.Factory mediaSourceFactory =
|
||||||
new ProgressiveMediaSource.Factory(
|
new ProgressiveMediaSource.Factory(
|
||||||
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -267,7 +274,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
||||||
@ -299,10 +306,13 @@ public class DefaultPreloadManagerTest {
|
|||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
||||||
.containsExactly(mediaItem2, mediaItem1, mediaItem0)
|
.containsExactly(mediaItem2, mediaItem1, mediaItem0)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_sourceHandedOverToPlayerDuringPreloading_continuesPreloadingNextSource() {
|
public void invalidate_sourceHandedOverToPlayerDuringPreloading_continuesPreloadingNextSource()
|
||||||
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
||||||
rankingData -> {
|
rankingData -> {
|
||||||
@ -310,6 +320,8 @@ public class DefaultPreloadManagerTest {
|
|||||||
return new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
|
return new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
|
||||||
};
|
};
|
||||||
FakeMediaSourceFactory fakeMediaSourceFactory = new FakeMediaSourceFactory();
|
FakeMediaSourceFactory fakeMediaSourceFactory = new FakeMediaSourceFactory();
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -318,7 +330,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
||||||
@ -341,14 +353,17 @@ public class DefaultPreloadManagerTest {
|
|||||||
(source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
|
(source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
|
||||||
wrappedMediaSource0.setAllowPreparation(true);
|
wrappedMediaSource0.setAllowPreparation(true);
|
||||||
wrappedMediaSource1.setAllowPreparation(true);
|
wrappedMediaSource1.setAllowPreparation(true);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
runMainLooperUntil(() -> preloadManagerListener.onCompletedMediaItemRecords.size() == 1);
|
||||||
|
|
||||||
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem1);
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem1);
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_beforePreloadCompletedForLastInvalidate_preloadRespectsToLatestOrder() {
|
public void invalidate_beforePreloadCompletedForLastInvalidate_preloadRespectsToLatestOrder()
|
||||||
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
||||||
rankingData -> {
|
rankingData -> {
|
||||||
@ -356,6 +371,8 @@ public class DefaultPreloadManagerTest {
|
|||||||
return new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
|
return new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
|
||||||
};
|
};
|
||||||
FakeMediaSourceFactory fakeMediaSourceFactory = new FakeMediaSourceFactory();
|
FakeMediaSourceFactory fakeMediaSourceFactory = new FakeMediaSourceFactory();
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -364,7 +381,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
||||||
@ -387,7 +404,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
|
|
||||||
preloadManager.invalidate();
|
preloadManager.invalidate();
|
||||||
wrappedMediaSource0.setAllowPreparation(true);
|
wrappedMediaSource0.setAllowPreparation(true);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
runMainLooperUntil(() -> preloadManagerListener.onCompletedMediaItemRecords.size() == 1);
|
||||||
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem0);
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem0);
|
||||||
|
|
||||||
@ -398,29 +415,36 @@ public class DefaultPreloadManagerTest {
|
|||||||
|
|
||||||
// Simulate the delay of the preparation of wrappedMediaSource1, which was triggered at the
|
// Simulate the delay of the preparation of wrappedMediaSource1, which was triggered at the
|
||||||
// first call of invalidate(). This is expected to result in nothing, as the whole flow of
|
// first call of invalidate(). This is expected to result in nothing, as the whole flow of
|
||||||
// preloading should respect the priority order triggered by the latest call of invalidate().
|
// preloading should respect the priority order triggered by the latest call of invalidate(),
|
||||||
|
// which will be verified by the order of items in
|
||||||
|
// preloadManagerListener.onCompletedMediaItemRecords.
|
||||||
wrappedMediaSource1.setAllowPreparation(true);
|
wrappedMediaSource1.setAllowPreparation(true);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords).isEmpty();
|
|
||||||
wrappedMediaSource2.setAllowPreparation(true);
|
wrappedMediaSource2.setAllowPreparation(true);
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
runMainLooperUntil(() -> preloadManagerListener.onCompletedMediaItemRecords.size() == 3);
|
||||||
assertThat(targetPreloadStatusControlCallStates).containsExactly(2, 1, 0).inOrder();
|
assertThat(targetPreloadStatusControlCallStates).containsExactly(2, 1, 0).inOrder();
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords)
|
||||||
.containsExactly(mediaItem2, mediaItem1, mediaItem0)
|
.containsExactly(mediaItem2, mediaItem1, mediaItem0)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_provideNullTargetPreloadStatus_sourcesSkippedForPreload() {
|
public void invalidate_provideNullTargetPreloadStatus_sourcesSkippedForPreload()
|
||||||
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
||||||
rankingData -> {
|
rankingData -> {
|
||||||
targetPreloadStatusControlCallStates.add(rankingData);
|
targetPreloadStatusControlCallStates.add(rankingData);
|
||||||
return null;
|
return (rankingData == 0)
|
||||||
|
? null
|
||||||
|
: new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
|
||||||
};
|
};
|
||||||
ProgressiveMediaSource.Factory mediaSourceFactory =
|
ProgressiveMediaSource.Factory mediaSourceFactory =
|
||||||
new ProgressiveMediaSource.Factory(
|
new ProgressiveMediaSource.Factory(
|
||||||
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
new DefaultDataSource.Factory(ApplicationProvider.getApplicationContext()));
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -429,7 +453,7 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
|
||||||
@ -443,24 +467,21 @@ public class DefaultPreloadManagerTest {
|
|||||||
.setMediaId("mediaId1")
|
.setMediaId("mediaId1")
|
||||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||||
.build();
|
.build();
|
||||||
MediaItem mediaItem2 =
|
|
||||||
mediaItemBuilder
|
|
||||||
.setMediaId("mediaId2")
|
|
||||||
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
|
||||||
.build();
|
|
||||||
preloadManager.add(mediaItem0, /* rankingData= */ 0);
|
preloadManager.add(mediaItem0, /* rankingData= */ 0);
|
||||||
preloadManager.add(mediaItem1, /* rankingData= */ 1);
|
preloadManager.add(mediaItem1, /* rankingData= */ 1);
|
||||||
preloadManager.add(mediaItem2, /* rankingData= */ 2);
|
|
||||||
|
|
||||||
preloadManager.invalidate();
|
preloadManager.invalidate();
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
runMainLooperUntil(() -> preloadManagerListener.onCompletedMediaItemRecords.size() == 1);
|
||||||
|
|
||||||
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1, 2);
|
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1);
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords).isEmpty();
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem1);
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidate_sourceHasPreloadException_continuesPreloadingNextSource() {
|
public void invalidate_sourceHasPreloadException_continuesPreloadingNextSource()
|
||||||
|
throws Exception {
|
||||||
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
ArrayList<Integer> targetPreloadStatusControlCallStates = new ArrayList<>();
|
||||||
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
|
||||||
rankingData -> {
|
rankingData -> {
|
||||||
@ -519,6 +540,8 @@ public class DefaultPreloadManagerTest {
|
|||||||
return mediaSource;
|
return mediaSource;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
HandlerThread preloadThread = new HandlerThread("preload");
|
||||||
|
preloadThread.start();
|
||||||
DefaultPreloadManager preloadManager =
|
DefaultPreloadManager preloadManager =
|
||||||
new DefaultPreloadManager(
|
new DefaultPreloadManager(
|
||||||
targetPreloadStatusControl,
|
targetPreloadStatusControl,
|
||||||
@ -527,20 +550,22 @@ public class DefaultPreloadManagerTest {
|
|||||||
bandwidthMeter,
|
bandwidthMeter,
|
||||||
rendererCapabilitiesListFactory,
|
rendererCapabilitiesListFactory,
|
||||||
allocator,
|
allocator,
|
||||||
Util.getCurrentOrMainLooper());
|
preloadThread.getLooper());
|
||||||
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
|
||||||
preloadManager.addListener(preloadManagerListener);
|
preloadManager.addListener(preloadManagerListener);
|
||||||
preloadManager.add(mediaItem0, /* rankingData= */ 0);
|
preloadManager.add(mediaItem0, /* rankingData= */ 0);
|
||||||
preloadManager.add(mediaItem1, /* rankingData= */ 1);
|
preloadManager.add(mediaItem1, /* rankingData= */ 1);
|
||||||
|
|
||||||
preloadManager.invalidate();
|
preloadManager.invalidate();
|
||||||
shadowOf(Looper.getMainLooper()).idle();
|
runMainLooperUntil(() -> preloadManagerListener.onCompletedMediaItemRecords.size() == 1);
|
||||||
|
|
||||||
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
assertThat(targetPreloadStatusControlCallStates).containsExactly(0, 1).inOrder();
|
||||||
assertThat(Iterables.getOnlyElement(preloadManagerListener.onErrorPreloadExceptionRecords))
|
assertThat(Iterables.getOnlyElement(preloadManagerListener.onErrorPreloadExceptionRecords))
|
||||||
.hasCauseThat()
|
.hasCauseThat()
|
||||||
.isEqualTo(causeException);
|
.isEqualTo(causeException);
|
||||||
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem1);
|
assertThat(preloadManagerListener.onCompletedMediaItemRecords).containsExactly(mediaItem1);
|
||||||
|
|
||||||
|
preloadThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user