mirror of
https://github.com/samsonjs/media.git
synced 2026-03-30 10:15:48 +00:00
Use removing and restarting state internally in DownloadManager
PiperOrigin-RevId: 227682159
This commit is contained in:
parent
c130723929
commit
a940d8bc9d
1 changed files with 100 additions and 84 deletions
|
|
@ -175,7 +175,6 @@ public final class DownloadManager {
|
|||
for (int i = 0; i < downloads.size(); i++) {
|
||||
downloads.get(i).clearStopFlags(STOP_FLAG_STOPPED);
|
||||
}
|
||||
maybeStartDownloads();
|
||||
logd("Downloads are started");
|
||||
}
|
||||
}
|
||||
|
|
@ -254,7 +253,7 @@ public final class DownloadManager {
|
|||
return false;
|
||||
}
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
if (downloads.get(i).isStarted()) {
|
||||
if (!downloads.get(i).isIdle()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -284,8 +283,7 @@ public final class DownloadManager {
|
|||
private void addDownloadForAction(DownloadAction action) {
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
Download download = downloads.get(i);
|
||||
if (download.action.isSameMedia(action)) {
|
||||
download.addAction(action);
|
||||
if (download.addAction(action)) {
|
||||
logd("Action is added to existing download", download);
|
||||
return;
|
||||
}
|
||||
|
|
@ -296,33 +294,27 @@ public final class DownloadManager {
|
|||
logd("Download is added", download);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through the download queue and starts any download if all of the following are true:
|
||||
*
|
||||
* <ul>
|
||||
* <li>It hasn't started yet.
|
||||
* <li>The maximum number of active downloads hasn't been reached.
|
||||
* </ul>
|
||||
*/
|
||||
private void maybeStartDownloads() {
|
||||
if (!initialized || released) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
maybeStartDownload(downloads.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeStartDownload(Download download) {
|
||||
if (download.action.isRemoveAction) {
|
||||
download.start();
|
||||
} else if (activeDownloads.size() < maxActiveDownloads) {
|
||||
if (initialized && !released && 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;
|
||||
|
|
@ -337,8 +329,8 @@ public final class DownloadManager {
|
|||
if (released) {
|
||||
return;
|
||||
}
|
||||
boolean stopped = !download.isStarted();
|
||||
if (stopped) {
|
||||
boolean idle = download.isIdle();
|
||||
if (idle) {
|
||||
activeDownloads.remove(download);
|
||||
}
|
||||
notifyListenersDownloadStateChange(download);
|
||||
|
|
@ -346,7 +338,7 @@ public final class DownloadManager {
|
|||
downloads.remove(download);
|
||||
saveActions();
|
||||
}
|
||||
if (stopped) {
|
||||
if (idle) {
|
||||
maybeStartDownloads();
|
||||
maybeNotifyListenersIdle();
|
||||
}
|
||||
|
|
@ -380,17 +372,18 @@ public final class DownloadManager {
|
|||
for (DownloadAction action : actions) {
|
||||
addDownloadForAction(action);
|
||||
}
|
||||
logd("Downloads are created.");
|
||||
initialized = true;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onInitialized(DownloadManager.this);
|
||||
}
|
||||
if (!actionQueue.isEmpty()) {
|
||||
while (!actionQueue.isEmpty()) {
|
||||
addDownloadForAction(actionQueue.remove());
|
||||
}
|
||||
saveActions();
|
||||
}
|
||||
logd("Downloads are created.");
|
||||
initialized = true;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onInitialized(DownloadManager.this);
|
||||
}
|
||||
maybeStartDownloads();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -433,7 +426,6 @@ public final class DownloadManager {
|
|||
private final int minRetryCount;
|
||||
private final long startTimeMs;
|
||||
private final ArrayDeque<DownloadAction> actionQueue;
|
||||
private DownloadAction action;
|
||||
/** The current state of the download. */
|
||||
@DownloadState.State private int state;
|
||||
|
||||
|
|
@ -456,29 +448,36 @@ public final class DownloadManager {
|
|||
this.startTimeMs = System.currentTimeMillis();
|
||||
actionQueue = new ArrayDeque<>();
|
||||
actionQueue.add(action);
|
||||
|
||||
// Don't notify listeners until we make sure the state doesn't change immediately.
|
||||
state = STATE_QUEUED;
|
||||
setActionAndUpdateState(action);
|
||||
downloadManager.maybeStartDownload(this);
|
||||
if (state == STATE_QUEUED) {
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
initialize(/* restart= */ false);
|
||||
}
|
||||
|
||||
public void addAction(DownloadAction newAction) {
|
||||
public boolean addAction(DownloadAction newAction) {
|
||||
DownloadAction action = actionQueue.peek();
|
||||
if (!action.isSameMedia(newAction)) {
|
||||
return false;
|
||||
}
|
||||
Assertions.checkState(action.type.equals(newAction.type));
|
||||
actionQueue.add(newAction);
|
||||
DownloadAction updatedAction = DownloadActionUtil.mergeActions(actionQueue);
|
||||
if (action.equals(updatedAction)) {
|
||||
return;
|
||||
}
|
||||
if (state == STATE_DOWNLOADING) {
|
||||
stopDownloadThread();
|
||||
} else {
|
||||
Assertions.checkState(state == STATE_QUEUED || state == STATE_STOPPED);
|
||||
setActionAndUpdateState(updatedAction);
|
||||
if (state == STATE_REMOVING) {
|
||||
Assertions.checkState(updatedAction.isRemoveAction);
|
||||
if (actionQueue.size() > 1) {
|
||||
setState(STATE_RESTARTING);
|
||||
}
|
||||
} else if (state == STATE_RESTARTING) {
|
||||
Assertions.checkState(updatedAction.isRemoveAction);
|
||||
if (actionQueue.size() == 1) {
|
||||
setState(STATE_REMOVING);
|
||||
}
|
||||
} else if (!action.equals(updatedAction)) {
|
||||
if (state == STATE_DOWNLOADING) {
|
||||
stopDownloadThread();
|
||||
} else {
|
||||
Assertions.checkState(state == STATE_QUEUED || state == STATE_STOPPED);
|
||||
initialize(/* restart= */ false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public DownloadState getDownloadState() {
|
||||
|
|
@ -490,20 +489,13 @@ public final class DownloadManager {
|
|||
downloadedBytes = downloader.getDownloadedBytes();
|
||||
totalBytes = downloader.getTotalBytes();
|
||||
}
|
||||
int newState = state;
|
||||
if (action.isRemoveAction) {
|
||||
if (state == STATE_DOWNLOADING) {
|
||||
newState = actionQueue.size() > 1 ? STATE_RESTARTING : STATE_REMOVING;
|
||||
} else if (state == STATE_COMPLETED || state == STATE_FAILED) {
|
||||
newState = STATE_REMOVED;
|
||||
}
|
||||
}
|
||||
DownloadAction action = actionQueue.peek();
|
||||
return new DownloadState(
|
||||
action.id,
|
||||
action.type,
|
||||
action.uri,
|
||||
action.customCacheKey,
|
||||
newState,
|
||||
state,
|
||||
downloadPercentage,
|
||||
downloadedBytes,
|
||||
totalBytes,
|
||||
|
|
@ -515,30 +507,24 @@ public final class DownloadManager {
|
|||
action.data);
|
||||
}
|
||||
|
||||
/** Returns whether the download is finished. */
|
||||
public boolean isFinished() {
|
||||
return state == STATE_FAILED || state == STATE_COMPLETED;
|
||||
return state == STATE_FAILED || state == STATE_COMPLETED || state == STATE_REMOVED;
|
||||
}
|
||||
|
||||
/** Returns whether the download is started. */
|
||||
public boolean isStarted() {
|
||||
return state == STATE_DOWNLOADING;
|
||||
public boolean isIdle() {
|
||||
return state != STATE_DOWNLOADING && state != STATE_REMOVING && state != STATE_RESTARTING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String actionString = action.isRemoveAction ? "remove" : "download";
|
||||
return id + ' ' + actionString + ' ' + DownloadState.getStateString(state);
|
||||
return id + ' ' + DownloadState.getStateString(state);
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
if (state != STATE_QUEUED) {
|
||||
return false;
|
||||
}
|
||||
downloader = downloaderFactory.createDownloader(action);
|
||||
downloadThread =
|
||||
new DownloadThread(
|
||||
this, downloader, action.isRemoveAction, minRetryCount, downloadManager.handler);
|
||||
startDownloadThread(actionQueue.peek());
|
||||
setState(STATE_DOWNLOADING);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -560,28 +546,53 @@ public final class DownloadManager {
|
|||
private void updateStopFlags(int mask, int flags) {
|
||||
stopFlags = (flags & mask) | (stopFlags & ~mask);
|
||||
if (stopFlags != 0) {
|
||||
if (!action.isRemoveAction) {
|
||||
if (state == STATE_DOWNLOADING) {
|
||||
stopDownloadThread();
|
||||
} else if (state == STATE_QUEUED) {
|
||||
setState(STATE_STOPPED);
|
||||
}
|
||||
if (state == STATE_DOWNLOADING) {
|
||||
stopDownloadThread();
|
||||
} else if (state == STATE_QUEUED) {
|
||||
setState(STATE_STOPPED);
|
||||
}
|
||||
} else if (state == STATE_STOPPED) {
|
||||
setState(STATE_QUEUED);
|
||||
startOrQueue(/* restart= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setActionAndUpdateState(DownloadAction action) {
|
||||
this.action = action;
|
||||
setState(!this.action.isRemoveAction && stopFlags != 0 ? STATE_STOPPED : STATE_QUEUED);
|
||||
private void initialize(boolean restart) {
|
||||
DownloadAction action = actionQueue.peek();
|
||||
if (action.isRemoveAction) {
|
||||
if (!downloadManager.released) {
|
||||
startDownloadThread(action);
|
||||
}
|
||||
setState(actionQueue.size() == 1 ? STATE_REMOVING : STATE_RESTARTING);
|
||||
} else if (stopFlags != 0) {
|
||||
setState(STATE_STOPPED);
|
||||
} else {
|
||||
startOrQueue(restart);
|
||||
}
|
||||
}
|
||||
|
||||
private void startOrQueue(boolean restart) {
|
||||
// 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);
|
||||
} else {
|
||||
downloadManager.maybeStartDownload(this);
|
||||
}
|
||||
if (state == STATE_QUEUED) {
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void setState(@DownloadState.State int newState) {
|
||||
if (state != newState) {
|
||||
state = newState;
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
state = newState;
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
|
||||
private void startDownloadThread(DownloadAction action) {
|
||||
downloader = downloaderFactory.createDownloader(action);
|
||||
downloadThread =
|
||||
new DownloadThread(
|
||||
this, downloader, action.isRemoveAction, minRetryCount, downloadManager.handler);
|
||||
}
|
||||
|
||||
private void stopDownloadThread() {
|
||||
|
|
@ -591,18 +602,23 @@ public final class DownloadManager {
|
|||
private void onDownloadThreadStopped(@Nullable Throwable finalError) {
|
||||
failureReason = FAILURE_REASON_NONE;
|
||||
if (!downloadThread.isCanceled) {
|
||||
if (finalError != null) {
|
||||
if (finalError != null && state != STATE_REMOVING && state != STATE_RESTARTING) {
|
||||
failureReason = FAILURE_REASON_UNKNOWN;
|
||||
setState(STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
if (actionQueue.size() == 1) {
|
||||
if (state == STATE_REMOVING) {
|
||||
setState(STATE_REMOVED);
|
||||
} else {
|
||||
Assertions.checkState(state == STATE_DOWNLOADING);
|
||||
setState(STATE_COMPLETED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
actionQueue.remove();
|
||||
}
|
||||
if (!actionQueue.isEmpty()) {
|
||||
setActionAndUpdateState(actionQueue.peek());
|
||||
} else {
|
||||
setState(STATE_COMPLETED);
|
||||
}
|
||||
initialize(/* restart= */ state == STATE_DOWNLOADING);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue