diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java index 035d3a90b0..c8c02d4980 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java @@ -25,6 +25,7 @@ import static com.google.android.exoplayer2.offline.DownloadState.STATE_REMOVED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_REMOVING; import static com.google.android.exoplayer2.offline.DownloadState.STATE_RESTARTING; import static com.google.android.exoplayer2.offline.DownloadState.STATE_STOPPED; +import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY; import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_STOPPED; import android.os.ConditionVariable; @@ -127,7 +128,7 @@ public final class DownloadManager { this.downloaderFactory = downloaderFactory; this.maxActiveDownloads = maxSimultaneousDownloads; this.minRetryCount = minRetryCount; - this.stickyStopFlags = STOP_FLAG_STOPPED; + this.stickyStopFlags = STOP_FLAG_STOPPED | STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY; downloads = new ArrayList<>(); activeDownloads = new ArrayList<>(); @@ -169,25 +170,31 @@ public final class DownloadManager { /** Starts the downloads. */ public void startDownloads() { - Assertions.checkState(!released); - if (stickyStopFlags != 0) { - stickyStopFlags = 0; - for (int i = 0; i < downloads.size(); i++) { - downloads.get(i).clearStopFlags(STOP_FLAG_STOPPED); - } - logd("Downloads are started"); - } + clearStopFlags(STOP_FLAG_STOPPED); } /** Stops all of the downloads. Call {@link #startDownloads()} to restart downloads. */ public void stopDownloads() { + setStopFlags(STOP_FLAG_STOPPED); + } + + private void setStopFlags(int flags) { + updateStopFlags(flags, flags); + } + + private void clearStopFlags(int flags) { + updateStopFlags(flags, 0); + } + + private void updateStopFlags(int flags, int values) { Assertions.checkState(!released); - if (stickyStopFlags == 0) { - stickyStopFlags = STOP_FLAG_STOPPED; + int updatedStickyStopFlags = (values & flags) | (stickyStopFlags & ~flags); + if (stickyStopFlags != updatedStickyStopFlags) { + stickyStopFlags = updatedStickyStopFlags; for (int i = 0; i < downloads.size(); i++) { - downloads.get(i).setStopFlags(STOP_FLAG_STOPPED); + downloads.get(i).updateStopFlags(flags, values); } - logd("Downloads are stopping"); + logdFlags("Sticky stop flags are updated", updatedStickyStopFlags); } } @@ -269,10 +276,8 @@ public final class DownloadManager { if (released) { return; } + setStopFlags(STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY); released = true; - for (int i = 0; i < downloads.size(); i++) { - downloads.get(i).queue(); - } final ConditionVariable fileIOFinishedCondition = new ConditionVariable(); fileIOHandler.post(fileIOFinishedCondition::open); fileIOFinishedCondition.block(); @@ -294,27 +299,14 @@ public final class DownloadManager { logd("Download is added", download); } - private void maybeStartDownloads() { - for (int i = 0; i < downloads.size(); i++) { - maybeStartDownload(downloads.get(i)); - } - } - private void maybeStartDownload(Download download) { - if (initialized && !released && activeDownloads.size() < maxActiveDownloads) { + if (activeDownloads.size() < maxActiveDownloads) { if (download.start()) { activeDownloads.add(download); } } } - private void maybeRestartDownload(Download download) { - Assertions.checkState(activeDownloads.contains(download)); - if (initialized && !released) { - download.start(); - } - } - private void maybeNotifyListenersIdle() { if (!isIdle()) { return; @@ -339,7 +331,9 @@ public final class DownloadManager { saveActions(); } if (idle) { - maybeStartDownloads(); + for (int i = 0; i < downloads.size(); i++) { + maybeStartDownload(downloads.get(i)); + } maybeNotifyListenersIdle(); } } @@ -383,7 +377,7 @@ public final class DownloadManager { for (Listener listener : listeners) { listener.onInitialized(DownloadManager.this); } - maybeStartDownloads(); + clearStopFlags(STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY); }); }); } @@ -415,7 +409,15 @@ public final class DownloadManager { } private static void logd(String message, Download download) { - logd(message + ": " + download); + if (DEBUG) { + logd(message + ": " + download); + } + } + + private static void logdFlags(String message, int flags) { + if (DEBUG) { + logd(message + ": " + Integer.toBinaryString(flags)); + } } private static final class Download { @@ -529,22 +531,16 @@ public final class DownloadManager { return true; } - public void setStopFlags(int stopFlags) { - updateStopFlags(stopFlags, stopFlags); + public void setStopFlags(int flags) { + updateStopFlags(flags, flags); } - public void clearStopFlags(int stopFlags) { - updateStopFlags(stopFlags, 0); + public void clearStopFlags(int flags) { + updateStopFlags(flags, 0); } - public void queue() { - if (state == STATE_DOWNLOADING) { - stopDownloadThread(); - } - } - - private void updateStopFlags(int mask, int flags) { - stopFlags = (flags & mask) | (stopFlags & ~mask); + public void updateStopFlags(int flags, int values) { + stopFlags = (values & flags) | (stopFlags & ~flags); if (stopFlags != 0) { if (state == STATE_DOWNLOADING) { stopDownloadThread(); @@ -574,7 +570,7 @@ public final class DownloadManager { // Set to queued state but don't notify listeners until we make sure we can't start now. state = STATE_QUEUED; if (restart) { - downloadManager.maybeRestartDownload(this); + start(); } else { downloadManager.maybeStartDownload(this); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java index 86ea0d51f6..eed32720a3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java @@ -73,15 +73,20 @@ public final class DownloadState { /** The download is failed because of unknown reason. */ public static final int FAILURE_REASON_UNKNOWN = 1; - /** Download stop flags. Possible flag value is {@link #STOP_FLAG_STOPPED}. */ + /** + * Download stop flags. Possible flag values are {@link #STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY} and + * {@link #STOP_FLAG_STOPPED}. + */ @Documented @Retention(RetentionPolicy.SOURCE) @IntDef( flag = true, - value = {STOP_FLAG_STOPPED}) + value = {STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY, STOP_FLAG_STOPPED}) public @interface StopFlags {} + /** Download can't be started as the manager isn't ready. */ + public static final int STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY = 1; /** All downloads are stopped by the application. */ - public static final int STOP_FLAG_STOPPED = 1; + public static final int STOP_FLAG_STOPPED = 1 << 1; /** Returns the state string for the given state value. */ public static String getStateString(@State int state) {