Use stop flag to prevent download start when not initialization/released

PiperOrigin-RevId: 228324452
This commit is contained in:
eguven 2019-01-08 15:14:04 +00:00 committed by Oliver Woodman
parent 255a34d367
commit 0b56a03880
2 changed files with 50 additions and 49 deletions

View File

@ -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_REMOVING;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_RESTARTING; 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.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 static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_STOPPED;
import android.os.ConditionVariable; import android.os.ConditionVariable;
@ -127,7 +128,7 @@ public final class DownloadManager {
this.downloaderFactory = downloaderFactory; this.downloaderFactory = downloaderFactory;
this.maxActiveDownloads = maxSimultaneousDownloads; this.maxActiveDownloads = maxSimultaneousDownloads;
this.minRetryCount = minRetryCount; this.minRetryCount = minRetryCount;
this.stickyStopFlags = STOP_FLAG_STOPPED; this.stickyStopFlags = STOP_FLAG_STOPPED | STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY;
downloads = new ArrayList<>(); downloads = new ArrayList<>();
activeDownloads = new ArrayList<>(); activeDownloads = new ArrayList<>();
@ -169,25 +170,31 @@ public final class DownloadManager {
/** Starts the downloads. */ /** Starts the downloads. */
public void startDownloads() { public void startDownloads() {
Assertions.checkState(!released); clearStopFlags(STOP_FLAG_STOPPED);
if (stickyStopFlags != 0) {
stickyStopFlags = 0;
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).clearStopFlags(STOP_FLAG_STOPPED);
}
logd("Downloads are started");
}
} }
/** Stops all of the downloads. Call {@link #startDownloads()} to restart downloads. */ /** Stops all of the downloads. Call {@link #startDownloads()} to restart downloads. */
public void stopDownloads() { public void stopDownloads() {
Assertions.checkState(!released); setStopFlags(STOP_FLAG_STOPPED);
if (stickyStopFlags == 0) {
stickyStopFlags = STOP_FLAG_STOPPED;
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).setStopFlags(STOP_FLAG_STOPPED);
} }
logd("Downloads are stopping");
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);
int updatedStickyStopFlags = (values & flags) | (stickyStopFlags & ~flags);
if (stickyStopFlags != updatedStickyStopFlags) {
stickyStopFlags = updatedStickyStopFlags;
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).updateStopFlags(flags, values);
}
logdFlags("Sticky stop flags are updated", updatedStickyStopFlags);
} }
} }
@ -269,10 +276,8 @@ public final class DownloadManager {
if (released) { if (released) {
return; return;
} }
setStopFlags(STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY);
released = true; released = true;
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).queue();
}
final ConditionVariable fileIOFinishedCondition = new ConditionVariable(); final ConditionVariable fileIOFinishedCondition = new ConditionVariable();
fileIOHandler.post(fileIOFinishedCondition::open); fileIOHandler.post(fileIOFinishedCondition::open);
fileIOFinishedCondition.block(); fileIOFinishedCondition.block();
@ -294,27 +299,14 @@ public final class DownloadManager {
logd("Download is added", download); 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) { private void maybeStartDownload(Download download) {
if (initialized && !released && activeDownloads.size() < maxActiveDownloads) { if (activeDownloads.size() < maxActiveDownloads) {
if (download.start()) { if (download.start()) {
activeDownloads.add(download); activeDownloads.add(download);
} }
} }
} }
private void maybeRestartDownload(Download download) {
Assertions.checkState(activeDownloads.contains(download));
if (initialized && !released) {
download.start();
}
}
private void maybeNotifyListenersIdle() { private void maybeNotifyListenersIdle() {
if (!isIdle()) { if (!isIdle()) {
return; return;
@ -339,7 +331,9 @@ public final class DownloadManager {
saveActions(); saveActions();
} }
if (idle) { if (idle) {
maybeStartDownloads(); for (int i = 0; i < downloads.size(); i++) {
maybeStartDownload(downloads.get(i));
}
maybeNotifyListenersIdle(); maybeNotifyListenersIdle();
} }
} }
@ -383,7 +377,7 @@ public final class DownloadManager {
for (Listener listener : listeners) { for (Listener listener : listeners) {
listener.onInitialized(DownloadManager.this); listener.onInitialized(DownloadManager.this);
} }
maybeStartDownloads(); clearStopFlags(STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY);
}); });
}); });
} }
@ -415,8 +409,16 @@ public final class DownloadManager {
} }
private static void logd(String message, Download download) { private static void logd(String message, Download download) {
if (DEBUG) {
logd(message + ": " + download); logd(message + ": " + download);
} }
}
private static void logdFlags(String message, int flags) {
if (DEBUG) {
logd(message + ": " + Integer.toBinaryString(flags));
}
}
private static final class Download { private static final class Download {
@ -529,22 +531,16 @@ public final class DownloadManager {
return true; return true;
} }
public void setStopFlags(int stopFlags) { public void setStopFlags(int flags) {
updateStopFlags(stopFlags, stopFlags); updateStopFlags(flags, flags);
} }
public void clearStopFlags(int stopFlags) { public void clearStopFlags(int flags) {
updateStopFlags(stopFlags, 0); updateStopFlags(flags, 0);
} }
public void queue() { public void updateStopFlags(int flags, int values) {
if (state == STATE_DOWNLOADING) { stopFlags = (values & flags) | (stopFlags & ~flags);
stopDownloadThread();
}
}
private void updateStopFlags(int mask, int flags) {
stopFlags = (flags & mask) | (stopFlags & ~mask);
if (stopFlags != 0) { if (stopFlags != 0) {
if (state == STATE_DOWNLOADING) { if (state == STATE_DOWNLOADING) {
stopDownloadThread(); 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. // Set to queued state but don't notify listeners until we make sure we can't start now.
state = STATE_QUEUED; state = STATE_QUEUED;
if (restart) { if (restart) {
downloadManager.maybeRestartDownload(this); start();
} else { } else {
downloadManager.maybeStartDownload(this); downloadManager.maybeStartDownload(this);
} }

View File

@ -73,15 +73,20 @@ public final class DownloadState {
/** The download is failed because of unknown reason. */ /** The download is failed because of unknown reason. */
public static final int FAILURE_REASON_UNKNOWN = 1; 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 @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef( @IntDef(
flag = true, flag = true,
value = {STOP_FLAG_STOPPED}) value = {STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY, STOP_FLAG_STOPPED})
public @interface StopFlags {} 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. */ /** 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. */ /** Returns the state string for the given state value. */
public static String getStateString(@State int state) { public static String getStateString(@State int state) {