mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Hide internal DownloadManager states
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=188481259
This commit is contained in:
parent
a58bffbe52
commit
e13789bfcc
3 changed files with 128 additions and 96 deletions
|
|
@ -16,12 +16,10 @@
|
||||||
package com.google.android.exoplayer2.offline;
|
package com.google.android.exoplayer2.offline;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_CANCELED;
|
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_CANCELED;
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_CANCELING;
|
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_ENDED;
|
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_ENDED;
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_ERROR;
|
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_ERROR;
|
||||||
|
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_QUEUED;
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STARTED;
|
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STARTED;
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STOPPING;
|
|
||||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_WAITING;
|
|
||||||
|
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
@ -31,7 +29,6 @@ import android.support.annotation.IntDef;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.offline.DownloadAction.Deserializer;
|
import com.google.android.exoplayer2.offline.DownloadAction.Deserializer;
|
||||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState.State;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -264,7 +261,7 @@ public final class DownloadManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < tasks.size(); i++) {
|
for (int i = 0; i < tasks.size(); i++) {
|
||||||
if (tasks.get(i).isRunning()) {
|
if (tasks.get(i).isActive()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +341,7 @@ public final class DownloadManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logd("Task state is changed", downloadTask);
|
logd("Task state is changed", downloadTask);
|
||||||
boolean stopped = !downloadTask.isRunning();
|
boolean stopped = !downloadTask.isActive();
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
activeDownloadTasks.remove(downloadTask);
|
activeDownloadTasks.remove(downloadTask);
|
||||||
}
|
}
|
||||||
|
|
@ -446,62 +443,39 @@ public final class DownloadManager {
|
||||||
/**
|
/**
|
||||||
* Task states.
|
* Task states.
|
||||||
*
|
*
|
||||||
* <p>Transition map (vertical states are source states):
|
* <p>Transition diagram:
|
||||||
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* +-------+-------+-----+---------+--------+--------+-----+
|
* -> canceled
|
||||||
* |waiting|started|ended|canceling|canceled|stopping|error|
|
* queued <-> started -> ended
|
||||||
* +---------+-------+-------+-----+---------+--------+--------+-----+
|
* -> error
|
||||||
* |waiting | | X | | X | | | |
|
|
||||||
* |started | | | X | X | | X | X |
|
|
||||||
* |canceling| | | | | X | | |
|
|
||||||
* |stopping | X | | | | | | |
|
|
||||||
* +---------+-------+-------+-----+---------+--------+--------+-----+
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef({STATE_WAITING, STATE_STARTED, STATE_ENDED, STATE_CANCELING, STATE_CANCELED,
|
@IntDef({STATE_QUEUED, STATE_STARTED, STATE_ENDED, STATE_CANCELED, STATE_ERROR})
|
||||||
STATE_STOPPING, STATE_ERROR})
|
|
||||||
public @interface State {}
|
public @interface State {}
|
||||||
/** The task is waiting to be started. */
|
/** The task is waiting to be started. */
|
||||||
public static final int STATE_WAITING = 0;
|
public static final int STATE_QUEUED = 0;
|
||||||
/** The task is currently started. */
|
/** The task is currently started. */
|
||||||
public static final int STATE_STARTED = 1;
|
public static final int STATE_STARTED = 1;
|
||||||
/** The task completed. */
|
/** The task completed. */
|
||||||
public static final int STATE_ENDED = 2;
|
public static final int STATE_ENDED = 2;
|
||||||
/** The task is about to be canceled. */
|
|
||||||
public static final int STATE_CANCELING = 3;
|
|
||||||
/** The task was canceled. */
|
/** The task was canceled. */
|
||||||
public static final int STATE_CANCELED = 4;
|
public static final int STATE_CANCELED = 3;
|
||||||
/** The task is about to be stopped. */
|
|
||||||
public static final int STATE_STOPPING = 5;
|
|
||||||
/** The task failed. */
|
/** The task failed. */
|
||||||
public static final int STATE_ERROR = 6;
|
public static final int STATE_ERROR = 4;
|
||||||
|
|
||||||
/** Returns whether the task is running. */
|
|
||||||
public static boolean isRunning(int state) {
|
|
||||||
return state == STATE_STARTED || state == STATE_STOPPING || state == STATE_CANCELING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether the task is finished. */
|
|
||||||
public static boolean isFinished(int state) {
|
|
||||||
return state == STATE_ERROR || state == STATE_ENDED || state == STATE_CANCELED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_WAITING:
|
case STATE_QUEUED:
|
||||||
return "WAITING";
|
return "QUEUED";
|
||||||
case STATE_STARTED:
|
case STATE_STARTED:
|
||||||
return "STARTED";
|
return "STARTED";
|
||||||
case STATE_ENDED:
|
case STATE_ENDED:
|
||||||
return "ENDED";
|
return "ENDED";
|
||||||
case STATE_CANCELING:
|
|
||||||
return "CANCELING";
|
|
||||||
case STATE_CANCELED:
|
case STATE_CANCELED:
|
||||||
return "CANCELED";
|
return "CANCELED";
|
||||||
case STATE_STOPPING:
|
|
||||||
return "STOPPING";
|
|
||||||
case STATE_ERROR:
|
case STATE_ERROR:
|
||||||
return "ERROR";
|
return "ERROR";
|
||||||
default:
|
default:
|
||||||
|
|
@ -531,7 +505,7 @@ public final class DownloadManager {
|
||||||
private DownloadState(
|
private DownloadState(
|
||||||
int taskId,
|
int taskId,
|
||||||
DownloadAction downloadAction,
|
DownloadAction downloadAction,
|
||||||
int state,
|
@State int state,
|
||||||
float downloadPercentage,
|
float downloadPercentage,
|
||||||
long downloadedBytes,
|
long downloadedBytes,
|
||||||
Throwable error) {
|
Throwable error) {
|
||||||
|
|
@ -543,24 +517,51 @@ public final class DownloadManager {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the task is finished. */
|
|
||||||
public boolean isFinished() {
|
|
||||||
return isFinished(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether the task is running. */
|
|
||||||
public boolean isRunning() {
|
|
||||||
return isRunning(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class DownloadTask implements Runnable {
|
private static final class DownloadTask implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task states.
|
||||||
|
*
|
||||||
|
* <p>Transition map (vertical states are source states):
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* +------+-------+-----+-----------+-----------+--------+--------+-----+
|
||||||
|
* |queued|started|ended|q_canceling|s_canceling|canceled|stopping|error|
|
||||||
|
* +-----------+------+-------+-----+-----------+-----------+--------+--------+-----+
|
||||||
|
* |queued | | X | | X | | | | |
|
||||||
|
* |started | | | X | | X | | X | X |
|
||||||
|
* |q_canceling| | | | | | X | | |
|
||||||
|
* |s_canceling| | | | | | X | | |
|
||||||
|
* |stopping | X | | | | | | | |
|
||||||
|
* +-----------+------+-------+-----+-----------+-----------+--------+--------+-----+
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({
|
||||||
|
STATE_QUEUED,
|
||||||
|
STATE_STARTED,
|
||||||
|
STATE_ENDED,
|
||||||
|
STATE_CANCELED,
|
||||||
|
STATE_ERROR,
|
||||||
|
STATE_QUEUED_CANCELING,
|
||||||
|
STATE_STARTED_CANCELING,
|
||||||
|
STATE_STARTED_STOPPING
|
||||||
|
})
|
||||||
|
public @interface InternalState {}
|
||||||
|
/** The task is about to be canceled. */
|
||||||
|
public static final int STATE_QUEUED_CANCELING = 5;
|
||||||
|
/** The task is about to be canceled. */
|
||||||
|
public static final int STATE_STARTED_CANCELING = 6;
|
||||||
|
/** The task is about to be stopped. */
|
||||||
|
public static final int STATE_STARTED_STOPPING = 7;
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private final DownloadManager downloadManager;
|
private final DownloadManager downloadManager;
|
||||||
private final DownloadAction downloadAction;
|
private final DownloadAction downloadAction;
|
||||||
private final int minRetryCount;
|
private final int minRetryCount;
|
||||||
private volatile @State int currentState;
|
private volatile @InternalState int currentState;
|
||||||
private volatile Downloader downloader;
|
private volatile Downloader downloader;
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private Throwable error;
|
private Throwable error;
|
||||||
|
|
@ -570,28 +571,29 @@ public final class DownloadManager {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.downloadManager = downloadManager;
|
this.downloadManager = downloadManager;
|
||||||
this.downloadAction = downloadAction;
|
this.downloadAction = downloadAction;
|
||||||
this.currentState = STATE_WAITING;
|
this.currentState = STATE_QUEUED;
|
||||||
this.minRetryCount = minRetryCount;
|
this.minRetryCount = minRetryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadState getDownloadState() {
|
public DownloadState getDownloadState() {
|
||||||
|
int externalState = getExternalState();
|
||||||
return new DownloadState(
|
return new DownloadState(
|
||||||
id, downloadAction, currentState, getDownloadPercentage(), getDownloadedBytes(), error);
|
id, downloadAction, externalState, getDownloadPercentage(), getDownloadedBytes(), error);
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the state of the task. */
|
|
||||||
public @State int getState() {
|
|
||||||
return currentState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the task is finished. */
|
/** Returns whether the task is finished. */
|
||||||
public boolean isFinished() {
|
public boolean isFinished() {
|
||||||
return DownloadState.isFinished(currentState);
|
return currentState == STATE_ERROR
|
||||||
|
|| currentState == STATE_ENDED
|
||||||
|
|| currentState == STATE_CANCELED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the task is running. */
|
/** Returns whether the task is started. */
|
||||||
public boolean isRunning() {
|
public boolean isActive() {
|
||||||
return DownloadState.isRunning(currentState);
|
return currentState == STATE_QUEUED_CANCELING
|
||||||
|
|| currentState == STATE_STARTED
|
||||||
|
|| currentState == STATE_STARTED_STOPPING
|
||||||
|
|| currentState == STATE_STARTED_CANCELING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -621,52 +623,80 @@ public final class DownloadManager {
|
||||||
+ ' '
|
+ ' '
|
||||||
+ downloadAction.getData()
|
+ downloadAction.getData()
|
||||||
+ ' '
|
+ ' '
|
||||||
+ DownloadState.getStateString(currentState);
|
+ getStateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStateString() {
|
||||||
|
switch (currentState) {
|
||||||
|
case STATE_QUEUED_CANCELING:
|
||||||
|
case STATE_STARTED_CANCELING:
|
||||||
|
return "CANCELING";
|
||||||
|
case STATE_STARTED_STOPPING:
|
||||||
|
return "STOPPING";
|
||||||
|
default:
|
||||||
|
return DownloadState.getStateString(currentState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getExternalState() {
|
||||||
|
switch (currentState) {
|
||||||
|
case STATE_QUEUED_CANCELING:
|
||||||
|
return STATE_QUEUED;
|
||||||
|
case STATE_STARTED_CANCELING:
|
||||||
|
case STATE_STARTED_STOPPING:
|
||||||
|
return STATE_STARTED;
|
||||||
|
default:
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() {
|
private void start() {
|
||||||
if (changeStateAndNotify(STATE_WAITING, STATE_STARTED)) {
|
if (changeStateAndNotify(STATE_QUEUED, STATE_STARTED)) {
|
||||||
thread = new Thread(this);
|
thread = new Thread(this);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canStart() {
|
private boolean canStart() {
|
||||||
return currentState == STATE_WAITING;
|
return currentState == STATE_QUEUED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancel() {
|
private void cancel() {
|
||||||
if (changeStateAndNotify(STATE_WAITING, STATE_CANCELING)) {
|
if (changeStateAndNotify(STATE_QUEUED, STATE_QUEUED_CANCELING)) {
|
||||||
downloadManager.handler.post(new Runnable() {
|
downloadManager.handler.post(
|
||||||
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
changeStateAndNotify(STATE_CANCELING, STATE_CANCELED);
|
changeStateAndNotify(STATE_QUEUED_CANCELING, STATE_CANCELED);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (changeStateAndNotify(STATE_STARTED, STATE_CANCELING)) {
|
} else if (changeStateAndNotify(STATE_STARTED, STATE_STARTED_CANCELING)) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stop() {
|
private void stop() {
|
||||||
if (changeStateAndNotify(STATE_STARTED, STATE_STOPPING)) {
|
if (changeStateAndNotify(STATE_STARTED, STATE_STARTED_STOPPING)) {
|
||||||
downloadManager.logd("Stopping", this);
|
downloadManager.logd("Stopping", this);
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean changeStateAndNotify(@State int oldState, @State int newState) {
|
private boolean changeStateAndNotify(@InternalState int oldState, @InternalState int newState) {
|
||||||
return changeStateAndNotify(oldState, newState, null);
|
return changeStateAndNotify(oldState, newState, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean changeStateAndNotify(@State int oldState, @State int newState,
|
private boolean changeStateAndNotify(
|
||||||
Throwable error) {
|
@InternalState int oldState, @InternalState int newState, Throwable error) {
|
||||||
if (currentState != oldState) {
|
if (currentState != oldState) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
currentState = newState;
|
currentState = newState;
|
||||||
this.error = error;
|
this.error = error;
|
||||||
|
boolean isInternalState = currentState != getExternalState();
|
||||||
|
if (!isInternalState) {
|
||||||
downloadManager.onTaskStateChange(DownloadTask.this);
|
downloadManager.onTaskStateChange(DownloadTask.this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -707,13 +737,14 @@ public final class DownloadManager {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
final Throwable finalError = error;
|
final Throwable finalError = error;
|
||||||
downloadManager.handler.post(new Runnable() {
|
downloadManager.handler.post(
|
||||||
|
new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (changeStateAndNotify(STATE_STARTED,
|
if (changeStateAndNotify(
|
||||||
finalError != null ? STATE_ERROR : STATE_ENDED, finalError)
|
STATE_STARTED, finalError != null ? STATE_ERROR : STATE_ENDED, finalError)
|
||||||
|| changeStateAndNotify(STATE_CANCELING, STATE_CANCELED)
|
|| changeStateAndNotify(STATE_STARTED_CANCELING, STATE_CANCELED)
|
||||||
|| changeStateAndNotify(STATE_STOPPING, STATE_WAITING)) {
|
|| changeStateAndNotify(STATE_STARTED_STOPPING, STATE_QUEUED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
|
||||||
|
|
@ -607,8 +607,7 @@ public class DownloadManagerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeDownloadAction assertStopped() {
|
private FakeDownloadAction assertStopped() {
|
||||||
assertState(DownloadState.STATE_STOPPING);
|
return assertState(DownloadState.STATE_QUEUED);
|
||||||
return assertState(DownloadState.STATE_WAITING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeDownloadAction assertState(@State int expectedState) {
|
private FakeDownloadAction assertState(@State int expectedState) {
|
||||||
|
|
|
||||||
|
|
@ -67,12 +67,16 @@ public final class DownloadNotificationUtil {
|
||||||
int titleStringId = getTitleStringId(downloadState);
|
int titleStringId = getTitleStringId(downloadState);
|
||||||
notificationBuilder.setContentTitle(context.getResources().getString(titleStringId));
|
notificationBuilder.setContentTitle(context.getResources().getString(titleStringId));
|
||||||
|
|
||||||
if (downloadState.isRunning()) {
|
if (downloadState.state == DownloadState.STATE_STARTED) {
|
||||||
notificationBuilder.setOngoing(true);
|
notificationBuilder.setOngoing(true);
|
||||||
float percentage = downloadState.downloadPercentage;
|
float percentage = downloadState.downloadPercentage;
|
||||||
boolean indeterminate = Float.isNaN(percentage);
|
boolean indeterminate = Float.isNaN(percentage);
|
||||||
notificationBuilder.setProgress(100, indeterminate ? 0 : (int) percentage, indeterminate);
|
notificationBuilder.setProgress(100, indeterminate ? 0 : (int) percentage, indeterminate);
|
||||||
}
|
}
|
||||||
|
if (Util.SDK_INT >= 17) {
|
||||||
|
// Hide timestamp on the notification while download progresses.
|
||||||
|
notificationBuilder.setShowWhen(downloadState.state != DownloadState.STATE_STARTED);
|
||||||
|
}
|
||||||
|
|
||||||
if (downloadState.error != null && errorMessageProvider != null) {
|
if (downloadState.error != null && errorMessageProvider != null) {
|
||||||
message = errorMessageProvider.getErrorMessage(downloadState.error).second;
|
message = errorMessageProvider.getErrorMessage(downloadState.error).second;
|
||||||
|
|
@ -90,12 +94,10 @@ public final class DownloadNotificationUtil {
|
||||||
private static int getTitleStringId(DownloadState downloadState) {
|
private static int getTitleStringId(DownloadState downloadState) {
|
||||||
int titleStringId;
|
int titleStringId;
|
||||||
switch (downloadState.state) {
|
switch (downloadState.state) {
|
||||||
case DownloadState.STATE_WAITING:
|
case DownloadState.STATE_QUEUED:
|
||||||
titleStringId = R.string.exo_download_queued;
|
titleStringId = R.string.exo_download_queued;
|
||||||
break;
|
break;
|
||||||
case DownloadState.STATE_STARTED:
|
case DownloadState.STATE_STARTED:
|
||||||
case DownloadState.STATE_STOPPING:
|
|
||||||
case DownloadState.STATE_CANCELING:
|
|
||||||
titleStringId = R.string.exo_downloading;
|
titleStringId = R.string.exo_downloading;
|
||||||
break;
|
break;
|
||||||
case DownloadState.STATE_ENDED:
|
case DownloadState.STATE_ENDED:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue