Don't create Downloads until DownloadManager is initialized

PiperOrigin-RevId: 225824428
This commit is contained in:
eguven 2018-12-17 15:41:04 +00:00 committed by Oliver Woodman
parent f4fd3b12e6
commit 3d6707e2c4
6 changed files with 36 additions and 14 deletions

View File

@ -38,7 +38,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -93,6 +92,7 @@ public final class DownloadManager {
private final HandlerThread fileIOThread; private final HandlerThread fileIOThread;
private final Handler fileIOHandler; private final Handler fileIOHandler;
private final CopyOnWriteArraySet<Listener> listeners; private final CopyOnWriteArraySet<Listener> listeners;
private final ArrayDeque<DownloadAction> actionQueue;
private boolean initialized; private boolean initialized;
private boolean released; private boolean released;
@ -142,6 +142,7 @@ public final class DownloadManager {
fileIOHandler = new Handler(fileIOThread.getLooper()); fileIOHandler = new Handler(fileIOThread.getLooper());
listeners = new CopyOnWriteArraySet<>(); listeners = new CopyOnWriteArraySet<>();
actionQueue = new ArrayDeque<>();
loadActions(); loadActions();
logd("Created"); logd("Created");
@ -194,8 +195,8 @@ public final class DownloadManager {
*/ */
public void handleAction(DownloadAction action) { public void handleAction(DownloadAction action) {
Assertions.checkState(!released); Assertions.checkState(!released);
Download download = getDownloadForAction(action);
if (initialized) { if (initialized) {
Download download = getOrAddDownloadForAction(action);
saveActions(); saveActions();
maybeStartDownloads(); maybeStartDownloads();
if (download.state == STATE_QUEUED) { if (download.state == STATE_QUEUED) {
@ -204,6 +205,8 @@ public final class DownloadManager {
// reported to listeners. Do so now. // reported to listeners. Do so now.
notifyListenersDownloadStateChange(download); notifyListenersDownloadStateChange(download);
} }
} else {
actionQueue.add(action);
} }
} }
@ -281,7 +284,7 @@ public final class DownloadManager {
logd("Released"); logd("Released");
} }
private Download getDownloadForAction(DownloadAction action) { private Download getOrAddDownloadForAction(DownloadAction action) {
for (int i = 0; i < downloads.size(); i++) { for (int i = 0; i < downloads.size(); i++) {
Download download = downloads.get(i); Download download = downloads.get(i);
if (download.action.isSameMedia(action)) { if (download.action.isSameMedia(action)) {
@ -380,18 +383,18 @@ public final class DownloadManager {
if (released) { if (released) {
return; return;
} }
List<Download> pendingDownloads = new ArrayList<>(downloads);
downloads.clear();
for (DownloadAction action : actions) { for (DownloadAction action : actions) {
getDownloadForAction(action); getOrAddDownloadForAction(action);
} }
logd("Downloads are created."); logd("Downloads are created.");
initialized = true; initialized = true;
for (Listener listener : listeners) { for (Listener listener : listeners) {
listener.onInitialized(DownloadManager.this); listener.onInitialized(DownloadManager.this);
} }
if (!pendingDownloads.isEmpty()) { if (!actionQueue.isEmpty()) {
downloads.addAll(pendingDownloads); while (!actionQueue.isEmpty()) {
getOrAddDownloadForAction(actionQueue.remove());
}
saveActions(); saveActions();
} }
maybeStartDownloads(); maybeStartDownloads();

View File

@ -426,9 +426,9 @@ public class DownloadManagerTest {
actionFile, downloaderFactory, maxActiveDownloadTasks, MIN_RETRY_COUNT); actionFile, downloaderFactory, maxActiveDownloadTasks, MIN_RETRY_COUNT);
downloadManagerListener = downloadManagerListener =
new TestDownloadManagerListener(downloadManager, dummyMainThread); new TestDownloadManagerListener(downloadManager, dummyMainThread);
downloadManager.addListener(downloadManagerListener);
downloadManager.startDownloads(); downloadManager.startDownloads();
}); });
downloadManagerListener.waitUntilInitialized();
} catch (Throwable throwable) { } catch (Throwable throwable) {
throw new Exception(throwable); throw new Exception(throwable);
} }

View File

@ -247,7 +247,6 @@ public class DownloadManagerDashTest {
downloadManagerListener = downloadManagerListener =
new TestDownloadManagerListener(downloadManager, dummyMainThread); new TestDownloadManagerListener(downloadManager, dummyMainThread);
downloadManager.addListener(downloadManagerListener);
downloadManager.startDownloads(); downloadManager.startDownloads();
}); });
} }

View File

@ -124,7 +124,6 @@ public class DownloadServiceDashTest {
/* minRetryCount= */ 3); /* minRetryCount= */ 3);
downloadManagerListener = downloadManagerListener =
new TestDownloadManagerListener(dashDownloadManager, dummyMainThread); new TestDownloadManagerListener(dashDownloadManager, dummyMainThread);
dashDownloadManager.addListener(downloadManagerListener);
dashDownloadManager.startDownloads(); dashDownloadManager.startDownloads();
dashDownloadService = dashDownloadService =

View File

@ -21,6 +21,8 @@ import android.os.ConditionVariable;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper; import android.os.Looper;
import com.google.android.exoplayer2.util.Util;
import java.util.concurrent.atomic.AtomicReference;
/** Helper class to simulate main/UI thread in tests. */ /** Helper class to simulate main/UI thread in tests. */
public final class DummyMainThread { public final class DummyMainThread {
@ -58,13 +60,21 @@ public final class DummyMainThread {
if (Looper.myLooper() == handler.getLooper()) { if (Looper.myLooper() == handler.getLooper()) {
runnable.run(); runnable.run();
} else { } else {
final ConditionVariable finishedCondition = new ConditionVariable(); ConditionVariable finishedCondition = new ConditionVariable();
AtomicReference<Throwable> thrown = new AtomicReference<>();
handler.post( handler.post(
() -> { () -> {
try {
runnable.run(); runnable.run();
} catch (Throwable t) {
thrown.set(t);
}
finishedCondition.open(); finishedCondition.open();
}); });
assertThat(finishedCondition.block(timeoutMs)).isTrue(); assertThat(finishedCondition.block(timeoutMs)).isTrue();
if (thrown.get() != null) {
Util.sneakyThrow(thrown.get());
}
} }
} }

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.os.ConditionVariable;
import com.google.android.exoplayer2.offline.DownloadManager; import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState; import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
import java.util.HashMap; import java.util.HashMap;
@ -28,10 +29,12 @@ import java.util.concurrent.TimeUnit;
public final class TestDownloadManagerListener implements DownloadManager.Listener { public final class TestDownloadManagerListener implements DownloadManager.Listener {
private static final int TIMEOUT = 1000; private static final int TIMEOUT = 1000;
private static final int INITIALIZATION_TIMEOUT = 10000;
private final DownloadManager downloadManager; private final DownloadManager downloadManager;
private final DummyMainThread dummyMainThread; private final DummyMainThread dummyMainThread;
private final HashMap<String, ArrayBlockingQueue<Integer>> actionStates; private final HashMap<String, ArrayBlockingQueue<Integer>> actionStates;
private final ConditionVariable initializedCondition;
private CountDownLatch downloadFinishedCondition; private CountDownLatch downloadFinishedCondition;
@DownloadState.FailureReason private int failureReason; @DownloadState.FailureReason private int failureReason;
@ -41,6 +44,8 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
this.downloadManager = downloadManager; this.downloadManager = downloadManager;
this.dummyMainThread = dummyMainThread; this.dummyMainThread = dummyMainThread;
actionStates = new HashMap<>(); actionStates = new HashMap<>();
initializedCondition = new ConditionVariable();
downloadManager.addListener(this);
} }
public Integer pollStateChange(String taskId, long timeoutMs) throws InterruptedException { public Integer pollStateChange(String taskId, long timeoutMs) throws InterruptedException {
@ -53,7 +58,13 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
@Override @Override
public void onInitialized(DownloadManager downloadManager) { public void onInitialized(DownloadManager downloadManager) {
// Do nothing. initializedCondition.open();
}
public void waitUntilInitialized() {
if (!downloadManager.isInitialized()) {
assertThat(initializedCondition.block(INITIALIZATION_TIMEOUT)).isTrue();
}
} }
@Override @Override