mirror of
https://github.com/samsonjs/media.git
synced 2026-04-02 10:45:51 +00:00
Rename TaskState to DownloadState
PiperOrigin-RevId: 225145311
This commit is contained in:
parent
230a798f23
commit
4bf42bd2ad
8 changed files with 205 additions and 217 deletions
|
|
@ -27,6 +27,7 @@
|
|||
([#5169](https://github.com/google/ExoPlayer/issues/5169)).
|
||||
* DownloadManager:
|
||||
* Create only one task for all DownloadActions for the same content.
|
||||
* Rename TaskState to DownloadState.
|
||||
|
||||
### 2.9.2 ###
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ package com.google.android.exoplayer2.demo;
|
|||
|
||||
import android.app.Notification;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
import com.google.android.exoplayer2.offline.DownloadService;
|
||||
import com.google.android.exoplayer2.scheduler.PlatformScheduler;
|
||||
import com.google.android.exoplayer2.ui.DownloadNotificationUtil;
|
||||
|
|
@ -50,40 +50,40 @@ public class DemoDownloadService extends DownloadService {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Notification getForegroundNotification(TaskState[] taskStates) {
|
||||
protected Notification getForegroundNotification(DownloadState[] downloadStates) {
|
||||
return DownloadNotificationUtil.buildProgressNotification(
|
||||
/* context= */ this,
|
||||
R.drawable.ic_download,
|
||||
CHANNEL_ID,
|
||||
/* contentIntent= */ null,
|
||||
/* message= */ null,
|
||||
taskStates);
|
||||
downloadStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTaskStateChanged(TaskState taskState) {
|
||||
if (taskState.action.isRemoveAction) {
|
||||
protected void onDownloadStateChanged(DownloadState downloadState) {
|
||||
if (downloadState.action.isRemoveAction) {
|
||||
return;
|
||||
}
|
||||
Notification notification = null;
|
||||
if (taskState.state == TaskState.STATE_COMPLETED) {
|
||||
if (downloadState.state == DownloadState.STATE_COMPLETED) {
|
||||
notification =
|
||||
DownloadNotificationUtil.buildDownloadCompletedNotification(
|
||||
/* context= */ this,
|
||||
R.drawable.ic_download_done,
|
||||
CHANNEL_ID,
|
||||
/* contentIntent= */ null,
|
||||
Util.fromUtf8Bytes(taskState.action.data));
|
||||
} else if (taskState.state == TaskState.STATE_FAILED) {
|
||||
Util.fromUtf8Bytes(downloadState.action.data));
|
||||
} else if (downloadState.state == DownloadState.STATE_FAILED) {
|
||||
notification =
|
||||
DownloadNotificationUtil.buildDownloadFailedNotification(
|
||||
/* context= */ this,
|
||||
R.drawable.ic_download_done,
|
||||
CHANNEL_ID,
|
||||
/* contentIntent= */ null,
|
||||
Util.fromUtf8Bytes(taskState.action.data));
|
||||
Util.fromUtf8Bytes(downloadState.action.data));
|
||||
}
|
||||
int notificationId = FOREGROUND_NOTIFICATION_ID + 1 + taskState.taskId;
|
||||
int notificationId = FOREGROUND_NOTIFICATION_ID + 1 + downloadState.id;
|
||||
NotificationUtil.setNotification(this, notificationId, notification);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import com.google.android.exoplayer2.offline.ActionFile;
|
|||
import com.google.android.exoplayer2.offline.DownloadAction;
|
||||
import com.google.android.exoplayer2.offline.DownloadHelper;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
import com.google.android.exoplayer2.offline.DownloadService;
|
||||
import com.google.android.exoplayer2.offline.ProgressiveDownloadHelper;
|
||||
import com.google.android.exoplayer2.offline.StreamKey;
|
||||
|
|
@ -144,11 +144,11 @@ public class DownloadTracker implements DownloadManager.Listener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onTaskStateChanged(DownloadManager downloadManager, TaskState taskState) {
|
||||
DownloadAction action = taskState.action;
|
||||
public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) {
|
||||
DownloadAction action = downloadState.action;
|
||||
Uri uri = action.uri;
|
||||
if ((action.isRemoveAction && taskState.state == TaskState.STATE_COMPLETED)
|
||||
|| (!action.isRemoveAction && taskState.state == TaskState.STATE_FAILED)) {
|
||||
if ((action.isRemoveAction && downloadState.state == DownloadState.STATE_COMPLETED)
|
||||
|| (!action.isRemoveAction && downloadState.state == DownloadState.STATE_FAILED)) {
|
||||
// A download has been removed, or has failed. Stop tracking it.
|
||||
if (trackedDownloadStates.remove(uri) != null) {
|
||||
handleTrackedDownloadStatesChanged();
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.offline;
|
||||
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.TaskState.STATE_COMPLETED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.TaskState.STATE_FAILED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.TaskState.STATE_QUEUED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.TaskState.STATE_STARTED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_COMPLETED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_FAILED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_QUEUED;
|
||||
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STARTED;
|
||||
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
|
|
@ -58,41 +58,41 @@ public final class DownloadManager {
|
|||
*/
|
||||
void onInitialized(DownloadManager downloadManager);
|
||||
/**
|
||||
* Called when the state of a task changes.
|
||||
* Called when the state of a download changes.
|
||||
*
|
||||
* @param downloadManager The reporting instance.
|
||||
* @param taskState The state of the task.
|
||||
* @param downloadState The state of the download.
|
||||
*/
|
||||
void onTaskStateChanged(DownloadManager downloadManager, TaskState taskState);
|
||||
void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState);
|
||||
|
||||
/**
|
||||
* Called when there is no active task left.
|
||||
* Called when there is no active download left.
|
||||
*
|
||||
* @param downloadManager The reporting instance.
|
||||
*/
|
||||
void onIdle(DownloadManager downloadManager);
|
||||
}
|
||||
|
||||
/** The default maximum number of simultaneous download tasks. */
|
||||
/** The default maximum number of simultaneous downloads. */
|
||||
public static final int DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS = 1;
|
||||
/** The default minimum number of times a task must be retried before failing. */
|
||||
/** The default minimum number of times a download must be retried before failing. */
|
||||
public static final int DEFAULT_MIN_RETRY_COUNT = 5;
|
||||
|
||||
private static final String TAG = "DownloadManager";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final int maxActiveDownloadTasks;
|
||||
private final int maxActiveDownloads;
|
||||
private final int minRetryCount;
|
||||
private final ActionFile actionFile;
|
||||
private final DownloaderFactory downloaderFactory;
|
||||
private final ArrayList<Task> tasks;
|
||||
private final ArrayList<Task> activeDownloadTasks;
|
||||
private final ArrayList<Download> downloads;
|
||||
private final ArrayList<Download> activeDownloads;
|
||||
private final Handler handler;
|
||||
private final HandlerThread fileIOThread;
|
||||
private final Handler fileIOHandler;
|
||||
private final CopyOnWriteArraySet<Listener> listeners;
|
||||
|
||||
private int nextTaskId;
|
||||
private int nextDownloadId;
|
||||
private boolean initialized;
|
||||
private boolean released;
|
||||
private boolean downloadsStopped;
|
||||
|
|
@ -113,8 +113,8 @@ public final class DownloadManager {
|
|||
*
|
||||
* @param actionFile The file in which active actions are saved.
|
||||
* @param downloaderFactory A factory for creating {@link Downloader}s.
|
||||
* @param maxSimultaneousDownloads The maximum number of simultaneous download tasks.
|
||||
* @param minRetryCount The minimum number of times a task must be retried before failing.
|
||||
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
|
||||
* @param minRetryCount The minimum number of times a download must be retried before failing.
|
||||
*/
|
||||
public DownloadManager(
|
||||
File actionFile,
|
||||
|
|
@ -123,12 +123,12 @@ public final class DownloadManager {
|
|||
int minRetryCount) {
|
||||
this.actionFile = new ActionFile(actionFile);
|
||||
this.downloaderFactory = downloaderFactory;
|
||||
this.maxActiveDownloadTasks = maxSimultaneousDownloads;
|
||||
this.maxActiveDownloads = maxSimultaneousDownloads;
|
||||
this.minRetryCount = minRetryCount;
|
||||
this.downloadsStopped = true;
|
||||
|
||||
tasks = new ArrayList<>();
|
||||
activeDownloadTasks = new ArrayList<>();
|
||||
downloads = new ArrayList<>();
|
||||
activeDownloads = new ArrayList<>();
|
||||
|
||||
Looper looper = Looper.myLooper();
|
||||
if (looper == null) {
|
||||
|
|
@ -164,23 +164,23 @@ public final class DownloadManager {
|
|||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/** Starts the download tasks. */
|
||||
/** Starts the downloads. */
|
||||
public void startDownloads() {
|
||||
Assertions.checkState(!released);
|
||||
if (downloadsStopped) {
|
||||
downloadsStopped = false;
|
||||
maybeStartTasks();
|
||||
maybeStartDownloads();
|
||||
logd("Downloads are started");
|
||||
}
|
||||
}
|
||||
|
||||
/** Stops all of the download tasks. Call {@link #startDownloads()} to restart tasks. */
|
||||
/** Stops all of the downloads. Call {@link #startDownloads()} to restart downloads. */
|
||||
public void stopDownloads() {
|
||||
Assertions.checkState(!released);
|
||||
if (!downloadsStopped) {
|
||||
downloadsStopped = true;
|
||||
for (int i = 0; i < activeDownloadTasks.size(); i++) {
|
||||
activeDownloadTasks.get(i).stop();
|
||||
for (int i = 0; i < activeDownloads.size(); i++) {
|
||||
activeDownloads.get(i).stop();
|
||||
}
|
||||
logd("Downloads are stopping");
|
||||
}
|
||||
|
|
@ -189,64 +189,50 @@ public final class DownloadManager {
|
|||
/**
|
||||
* Handles the given action.
|
||||
*
|
||||
* <p>A task is created and added to the task queue if there isn't one already for the same
|
||||
* content.
|
||||
*
|
||||
* @param action The action to be executed.
|
||||
* @return The id of the newly created or the existing task.
|
||||
* @return The id of the newly created or the existing download.
|
||||
*/
|
||||
public int handleAction(DownloadAction action) {
|
||||
Assertions.checkState(!released);
|
||||
Task task = addTaskForAction(action);
|
||||
Download download = getDownloadForAction(action);
|
||||
if (initialized) {
|
||||
saveActions();
|
||||
maybeStartTasks();
|
||||
if (task.state == STATE_QUEUED) {
|
||||
// Task did not change out of its initial state, and so its initial state won't have been
|
||||
maybeStartDownloads();
|
||||
if (download.state == STATE_QUEUED) {
|
||||
// Download did not change out of its initial state, and so its initial state won't have
|
||||
// been
|
||||
// reported to listeners. Do so now.
|
||||
notifyListenersTaskStateChange(task);
|
||||
notifyListenersDownloadStateChange(download);
|
||||
}
|
||||
}
|
||||
return task.id;
|
||||
return download.id;
|
||||
}
|
||||
|
||||
/** Returns the number of tasks. */
|
||||
public int getTaskCount() {
|
||||
Assertions.checkState(!released);
|
||||
return tasks.size();
|
||||
}
|
||||
|
||||
/** Returns the number of download tasks. */
|
||||
/** Returns the number of downloads. */
|
||||
public int getDownloadCount() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
for (DownloadAction action : tasks.get(i).actionQueue) {
|
||||
if (!action.isRemoveAction) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
Assertions.checkState(!released);
|
||||
return downloads.size();
|
||||
}
|
||||
|
||||
/** Returns the state of a task, or null if no such task exists */
|
||||
public @Nullable TaskState getTaskState(int taskId) {
|
||||
/** Returns the state of a download, or null if no such download exists */
|
||||
@Nullable
|
||||
public DownloadState getDownloadState(int downloadId) {
|
||||
Assertions.checkState(!released);
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
Task task = tasks.get(i);
|
||||
if (task.id == taskId) {
|
||||
return task.getTaskState();
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
Download download = downloads.get(i);
|
||||
if (download.id == downloadId) {
|
||||
return download.getDownloadState();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns the states of all current tasks. */
|
||||
public TaskState[] getAllTaskStates() {
|
||||
/** Returns the states of all current downloads. */
|
||||
public DownloadState[] getAllDownloadStates() {
|
||||
Assertions.checkState(!released);
|
||||
TaskState[] states = new TaskState[tasks.size()];
|
||||
DownloadState[] states = new DownloadState[downloads.size()];
|
||||
for (int i = 0; i < states.length; i++) {
|
||||
states[i] = tasks.get(i).getTaskState();
|
||||
states[i] = downloads.get(i).getDownloadState();
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
|
@ -257,14 +243,14 @@ public final class DownloadManager {
|
|||
return initialized;
|
||||
}
|
||||
|
||||
/** Returns whether there are no active tasks. */
|
||||
/** Returns whether there are no active downloads. */
|
||||
public boolean isIdle() {
|
||||
Assertions.checkState(!released);
|
||||
if (!initialized) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
if (tasks.get(i).isStarted()) {
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
if (downloads.get(i).isStarted()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -272,16 +258,17 @@ public final class DownloadManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Stops all of the tasks and releases resources. If the action file isn't up to date, waits for
|
||||
* the changes to be written. The manager must not be accessed after this method has been called.
|
||||
* Stops all of the downloads and releases resources. If the action file isn't up to date, waits
|
||||
* for the changes to be written. The manager must not be accessed after this method has been
|
||||
* called.
|
||||
*/
|
||||
public void release() {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
released = true;
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
tasks.get(i).stop();
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
downloads.get(i).stop();
|
||||
}
|
||||
final ConditionVariable fileIOFinishedCondition = new ConditionVariable();
|
||||
fileIOHandler.post(fileIOFinishedCondition::open);
|
||||
|
|
@ -290,47 +277,47 @@ public final class DownloadManager {
|
|||
logd("Released");
|
||||
}
|
||||
|
||||
private Task addTaskForAction(DownloadAction action) {
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
Task task = tasks.get(i);
|
||||
if (task.action.isSameMedia(action)) {
|
||||
task.addAction(action);
|
||||
logd("Action is added to existing task", task);
|
||||
return task;
|
||||
private Download getDownloadForAction(DownloadAction action) {
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
Download download = downloads.get(i);
|
||||
if (download.action.isSameMedia(action)) {
|
||||
download.addAction(action);
|
||||
logd("Action is added to existing download", download);
|
||||
return download;
|
||||
}
|
||||
}
|
||||
Task task = new Task(nextTaskId++, this, downloaderFactory, action, minRetryCount);
|
||||
tasks.add(task);
|
||||
logd("Task is added", task);
|
||||
return task;
|
||||
Download download =
|
||||
new Download(nextDownloadId++, this, downloaderFactory, action, minRetryCount);
|
||||
downloads.add(download);
|
||||
logd("Download is added", download);
|
||||
return download;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through the task queue and starts any task if all of the following are true:
|
||||
* Iterates through the download queue and starts any download if all of the following are true:
|
||||
*
|
||||
* <ul>
|
||||
* <li>It hasn't started yet.
|
||||
* <li>If it's a download task then the maximum number of active downloads hasn't been reached.
|
||||
* <li>The maximum number of active downloads hasn't been reached.
|
||||
* </ul>
|
||||
*/
|
||||
private void maybeStartTasks() {
|
||||
private void maybeStartDownloads() {
|
||||
if (!initialized || released) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean skipDownloadActions = downloadsStopped
|
||||
|| activeDownloadTasks.size() == maxActiveDownloadTasks;
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
Task task = tasks.get(i);
|
||||
if (!task.canStart()) {
|
||||
boolean skipDownloads = downloadsStopped || activeDownloads.size() == maxActiveDownloads;
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
Download download = downloads.get(i);
|
||||
if (!download.canStart()) {
|
||||
continue;
|
||||
}
|
||||
boolean isRemoveAction = task.action.isRemoveAction;
|
||||
if (isRemoveAction || !skipDownloadActions) {
|
||||
task.start();
|
||||
boolean isRemoveAction = download.action.isRemoveAction;
|
||||
if (isRemoveAction || !skipDownloads) {
|
||||
download.start();
|
||||
if (!isRemoveAction) {
|
||||
activeDownloadTasks.add(task);
|
||||
skipDownloadActions = activeDownloadTasks.size() == maxActiveDownloadTasks;
|
||||
activeDownloads.add(download);
|
||||
skipDownloads = activeDownloads.size() == maxActiveDownloads;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -346,30 +333,30 @@ public final class DownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
private void onTaskStateChange(Task task) {
|
||||
private void onDownloadStateChange(Download download) {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
boolean stopped = !task.isStarted();
|
||||
boolean stopped = !download.isStarted();
|
||||
if (stopped) {
|
||||
activeDownloadTasks.remove(task);
|
||||
activeDownloads.remove(download);
|
||||
}
|
||||
notifyListenersTaskStateChange(task);
|
||||
if (task.isFinished()) {
|
||||
tasks.remove(task);
|
||||
notifyListenersDownloadStateChange(download);
|
||||
if (download.isFinished()) {
|
||||
downloads.remove(download);
|
||||
saveActions();
|
||||
}
|
||||
if (stopped) {
|
||||
maybeStartTasks();
|
||||
maybeStartDownloads();
|
||||
maybeNotifyListenersIdle();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListenersTaskStateChange(Task task) {
|
||||
logd("Task state is changed", task);
|
||||
TaskState taskState = task.getTaskState();
|
||||
private void notifyListenersDownloadStateChange(Download download) {
|
||||
logd("Download state is changed", download);
|
||||
DownloadState downloadState = download.getDownloadState();
|
||||
for (Listener listener : listeners) {
|
||||
listener.onTaskStateChanged(this, taskState);
|
||||
listener.onDownloadStateChanged(this, downloadState);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -390,27 +377,27 @@ public final class DownloadManager {
|
|||
if (released) {
|
||||
return;
|
||||
}
|
||||
List<Task> pendingTasks = new ArrayList<>(tasks);
|
||||
tasks.clear();
|
||||
List<Download> pendingDownloads = new ArrayList<>(downloads);
|
||||
downloads.clear();
|
||||
for (DownloadAction action : actions) {
|
||||
addTaskForAction(action);
|
||||
getDownloadForAction(action);
|
||||
}
|
||||
logd("Tasks are created.");
|
||||
logd("Downloads are created.");
|
||||
initialized = true;
|
||||
for (Listener listener : listeners) {
|
||||
listener.onInitialized(DownloadManager.this);
|
||||
}
|
||||
if (!pendingTasks.isEmpty()) {
|
||||
tasks.addAll(pendingTasks);
|
||||
if (!pendingDownloads.isEmpty()) {
|
||||
downloads.addAll(pendingDownloads);
|
||||
saveActions();
|
||||
}
|
||||
maybeStartTasks();
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
Task task = tasks.get(i);
|
||||
if (task.state == STATE_QUEUED) {
|
||||
// Task did not change out of its initial state, and so its initial state
|
||||
maybeStartDownloads();
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
Download download = downloads.get(i);
|
||||
if (download.state == STATE_QUEUED) {
|
||||
// Download did not change out of its initial state, and so its initial state
|
||||
// won't have been reported to listeners. Do so now.
|
||||
notifyListenersTaskStateChange(task);
|
||||
notifyListenersDownloadStateChange(download);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -421,9 +408,9 @@ public final class DownloadManager {
|
|||
if (released) {
|
||||
return;
|
||||
}
|
||||
ArrayList<DownloadAction> actions = new ArrayList<>(tasks.size());
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
actions.addAll(tasks.get(i).actionQueue);
|
||||
ArrayList<DownloadAction> actions = new ArrayList<>(downloads.size());
|
||||
for (int i = 0; i < downloads.size(); i++) {
|
||||
actions.addAll(downloads.get(i).actionQueue);
|
||||
}
|
||||
final DownloadAction[] actionsArray = actions.toArray(new DownloadAction[0]);
|
||||
fileIOHandler.post(
|
||||
|
|
@ -443,16 +430,16 @@ public final class DownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static void logd(String message, Task task) {
|
||||
logd(message + ": " + task);
|
||||
private static void logd(String message, Download download) {
|
||||
logd(message + ": " + download);
|
||||
}
|
||||
|
||||
/** Represents state of a task. */
|
||||
public static final class TaskState {
|
||||
/** Represents state of a download. */
|
||||
public static final class DownloadState {
|
||||
|
||||
/**
|
||||
* Task states. One of {@link #STATE_QUEUED}, {@link #STATE_STARTED}, {@link #STATE_COMPLETED}
|
||||
* or {@link #STATE_FAILED}.
|
||||
* Download states. One of {@link #STATE_QUEUED}, {@link #STATE_STARTED}, {@link
|
||||
* #STATE_COMPLETED} or {@link #STATE_FAILED}.
|
||||
*
|
||||
* <p>Transition diagram:
|
||||
*
|
||||
|
|
@ -465,13 +452,13 @@ public final class DownloadManager {
|
|||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({STATE_QUEUED, STATE_STARTED, STATE_COMPLETED, STATE_FAILED})
|
||||
public @interface State {}
|
||||
/** The task is waiting to be started. */
|
||||
/** The download is waiting to be started. */
|
||||
public static final int STATE_QUEUED = 0;
|
||||
/** The task is currently started. */
|
||||
/** The download is currently started. */
|
||||
public static final int STATE_STARTED = 1;
|
||||
/** The task completed. */
|
||||
/** The download completed. */
|
||||
public static final int STATE_COMPLETED = 2;
|
||||
/** The task failed. */
|
||||
/** The download failed. */
|
||||
public static final int STATE_FAILED = 3;
|
||||
|
||||
/** Returns the state string for the given state value. */
|
||||
|
|
@ -490,16 +477,15 @@ public final class DownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
/** The unique task id. */
|
||||
public final int taskId;
|
||||
/** The unique download id. */
|
||||
public final int id;
|
||||
/** The action being executed. */
|
||||
public final DownloadAction action;
|
||||
/** The state of the task. */
|
||||
/** The state of the download. */
|
||||
public final @State int state;
|
||||
|
||||
/**
|
||||
* The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if no estimate is available
|
||||
* or if this is a removal task.
|
||||
* The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if no estimate is available.
|
||||
*/
|
||||
public final float downloadPercentage;
|
||||
/** The total number of downloaded bytes. */
|
||||
|
|
@ -510,15 +496,15 @@ public final class DownloadManager {
|
|||
/** If {@link #state} is {@link #STATE_FAILED} then this is the cause, otherwise null. */
|
||||
@Nullable public final Throwable error;
|
||||
|
||||
private TaskState(
|
||||
int taskId,
|
||||
private DownloadState(
|
||||
int id,
|
||||
DownloadAction action,
|
||||
@State int state,
|
||||
float downloadPercentage,
|
||||
long downloadedBytes,
|
||||
long totalBytes,
|
||||
@Nullable Throwable error) {
|
||||
this.taskId = taskId;
|
||||
this.id = id;
|
||||
this.action = action;
|
||||
this.state = state;
|
||||
this.downloadPercentage = downloadPercentage;
|
||||
|
|
@ -529,7 +515,7 @@ public final class DownloadManager {
|
|||
|
||||
}
|
||||
|
||||
private static final class Task {
|
||||
private static final class Download {
|
||||
|
||||
/** Target states for the download thread. */
|
||||
@Documented
|
||||
|
|
@ -543,10 +529,10 @@ public final class DownloadManager {
|
|||
private final int minRetryCount;
|
||||
private final ArrayDeque<DownloadAction> actionQueue;
|
||||
private DownloadAction action;
|
||||
/** The current state of the task. */
|
||||
@TaskState.State private int state;
|
||||
/** The current state of the download. */
|
||||
@DownloadState.State private int state;
|
||||
/**
|
||||
* When started, this is the target state that the task will transition to when the download
|
||||
* When started, this is the target state that the download will transition to when the download
|
||||
* thread stops.
|
||||
*/
|
||||
@TargetState private volatile int targetState;
|
||||
|
|
@ -555,7 +541,7 @@ public final class DownloadManager {
|
|||
@MonotonicNonNull private DownloadThread downloadThread;
|
||||
@MonotonicNonNull private Throwable error;
|
||||
|
||||
private Task(
|
||||
private Download(
|
||||
int id,
|
||||
DownloadManager downloadManager,
|
||||
DownloaderFactory downloaderFactory,
|
||||
|
|
@ -586,11 +572,11 @@ public final class DownloadManager {
|
|||
} else {
|
||||
Assertions.checkState(state == STATE_QUEUED);
|
||||
action = updatedAction;
|
||||
downloadManager.onTaskStateChange(this);
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
public TaskState getTaskState() {
|
||||
public DownloadState getDownloadState() {
|
||||
float downloadPercentage = C.PERCENTAGE_UNSET;
|
||||
long downloadedBytes = 0;
|
||||
long totalBytes = C.LENGTH_UNSET;
|
||||
|
|
@ -599,16 +585,16 @@ public final class DownloadManager {
|
|||
downloadedBytes = downloader.getDownloadedBytes();
|
||||
totalBytes = downloader.getTotalBytes();
|
||||
}
|
||||
return new TaskState(
|
||||
return new DownloadState(
|
||||
id, action, state, downloadPercentage, downloadedBytes, totalBytes, error);
|
||||
}
|
||||
|
||||
/** Returns whether the task is finished. */
|
||||
/** Returns whether the download is finished. */
|
||||
public boolean isFinished() {
|
||||
return state == STATE_FAILED || state == STATE_COMPLETED;
|
||||
}
|
||||
|
||||
/** Returns whether the task is started. */
|
||||
/** Returns whether the download is started. */
|
||||
public boolean isStarted() {
|
||||
return state == STATE_STARTED;
|
||||
}
|
||||
|
|
@ -619,9 +605,9 @@ public final class DownloadManager {
|
|||
+ ' '
|
||||
+ (action.isRemoveAction ? "remove" : "download")
|
||||
+ ' '
|
||||
+ TaskState.getStateString(state)
|
||||
+ DownloadState.getStateString(state)
|
||||
+ ' '
|
||||
+ TaskState.getStateString(targetState);
|
||||
+ DownloadState.getStateString(targetState);
|
||||
}
|
||||
|
||||
public boolean canStart() {
|
||||
|
|
@ -637,7 +623,7 @@ public final class DownloadManager {
|
|||
downloadThread =
|
||||
new DownloadThread(
|
||||
this, downloader, action.isRemoveAction, minRetryCount, downloadManager.handler);
|
||||
downloadManager.onTaskStateChange(this);
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -650,7 +636,7 @@ public final class DownloadManager {
|
|||
// Internal methods running on the main thread.
|
||||
|
||||
private void stopDownloadThread() {
|
||||
this.targetState = TaskState.STATE_QUEUED;
|
||||
this.targetState = DownloadState.STATE_QUEUED;
|
||||
Assertions.checkNotNull(downloadThread).cancel();
|
||||
}
|
||||
|
||||
|
|
@ -664,19 +650,19 @@ public final class DownloadManager {
|
|||
} else {
|
||||
actionQueue.remove();
|
||||
if (!actionQueue.isEmpty()) {
|
||||
// Don't continue running. Wait to be restarted by maybeStartTasks().
|
||||
// Don't continue running. Wait to be restarted by maybeStartDownloads().
|
||||
state = STATE_QUEUED;
|
||||
action = actionQueue.peek();
|
||||
}
|
||||
}
|
||||
}
|
||||
downloadManager.onTaskStateChange(this);
|
||||
downloadManager.onDownloadStateChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DownloadThread implements Runnable {
|
||||
|
||||
private final Task task;
|
||||
private final Download download;
|
||||
private final Downloader downloader;
|
||||
private final boolean remove;
|
||||
private final int minRetryCount;
|
||||
|
|
@ -685,12 +671,12 @@ public final class DownloadManager {
|
|||
private volatile boolean isCanceled;
|
||||
|
||||
private DownloadThread(
|
||||
Task task,
|
||||
Download download,
|
||||
Downloader downloader,
|
||||
boolean remove,
|
||||
int minRetryCount,
|
||||
Handler callbackHandler) {
|
||||
this.task = task;
|
||||
this.download = download;
|
||||
this.downloader = downloader;
|
||||
this.remove = remove;
|
||||
this.minRetryCount = minRetryCount;
|
||||
|
|
@ -709,7 +695,7 @@ public final class DownloadManager {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
logd("Task is started", task);
|
||||
logd("Download is started", download);
|
||||
Throwable error = null;
|
||||
try {
|
||||
if (remove) {
|
||||
|
|
@ -725,14 +711,14 @@ public final class DownloadManager {
|
|||
if (!isCanceled) {
|
||||
long downloadedBytes = downloader.getDownloadedBytes();
|
||||
if (downloadedBytes != errorPosition) {
|
||||
logd("Reset error count. downloadedBytes = " + downloadedBytes, task);
|
||||
logd("Reset error count. downloadedBytes = " + downloadedBytes, download);
|
||||
errorPosition = downloadedBytes;
|
||||
errorCount = 0;
|
||||
}
|
||||
if (++errorCount > minRetryCount) {
|
||||
throw e;
|
||||
}
|
||||
logd("Download error. Retry " + errorCount, task);
|
||||
logd("Download error. Retry " + errorCount, download);
|
||||
Thread.sleep(getRetryDelayMillis(errorCount));
|
||||
}
|
||||
}
|
||||
|
|
@ -742,7 +728,7 @@ public final class DownloadManager {
|
|||
error = e;
|
||||
}
|
||||
final Throwable finalError = error;
|
||||
callbackHandler.post(() -> task.onDownloadThreadStopped(isCanceled ? null : finalError));
|
||||
callbackHandler.post(() -> download.onDownloadThreadStopped(isCanceled ? null : finalError));
|
||||
}
|
||||
|
||||
private int getRetryDelayMillis(int errorCount) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import android.os.IBinder;
|
|||
import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
import com.google.android.exoplayer2.scheduler.Requirements;
|
||||
import com.google.android.exoplayer2.scheduler.RequirementsWatcher;
|
||||
import com.google.android.exoplayer2.scheduler.Scheduler;
|
||||
|
|
@ -71,9 +71,9 @@ public abstract class DownloadService extends Service {
|
|||
private static final String TAG = "DownloadService";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// Keep the requirements helper for each DownloadService as long as there are tasks (and the
|
||||
// process is running). This allows tasks to resume when there's no scheduler. It may also allow
|
||||
// tasks the resume more quickly than when relying on the scheduler alone.
|
||||
// Keep the requirements helper for each DownloadService as long as there are downloads (and the
|
||||
// process is running). This allows downloads to resume when there's no scheduler. It may also
|
||||
// allow downloads the resume more quickly than when relying on the scheduler alone.
|
||||
private static final HashMap<Class<? extends DownloadService>, RequirementsHelper>
|
||||
requirementsHelpers = new HashMap<>();
|
||||
private static final Requirements DEFAULT_REQUIREMENTS =
|
||||
|
|
@ -99,7 +99,7 @@ public abstract class DownloadService extends Service {
|
|||
* <p>If {@code foregroundNotificationId} isn't {@link #FOREGROUND_NOTIFICATION_ID_NONE} (value
|
||||
* {@value #FOREGROUND_NOTIFICATION_ID_NONE}) the service runs in the foreground with {@link
|
||||
* #DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL}. In that case {@link
|
||||
* #getForegroundNotification(TaskState[])} should be overridden in the subclass.
|
||||
* #getForegroundNotification(DownloadState[])} should be overridden in the subclass.
|
||||
*
|
||||
* @param foregroundNotificationId The notification id for the foreground notification, or {@link
|
||||
* #FOREGROUND_NOTIFICATION_ID_NONE} (value {@value #FOREGROUND_NOTIFICATION_ID_NONE})
|
||||
|
|
@ -110,7 +110,7 @@ public abstract class DownloadService extends Service {
|
|||
|
||||
/**
|
||||
* Creates a DownloadService which will run in the foreground. {@link
|
||||
* #getForegroundNotification(TaskState[])} should be overridden in the subclass.
|
||||
* #getForegroundNotification(DownloadState[])} should be overridden in the subclass.
|
||||
*
|
||||
* @param foregroundNotificationId The notification id for the foreground notification, must not
|
||||
* be 0.
|
||||
|
|
@ -128,7 +128,7 @@ public abstract class DownloadService extends Service {
|
|||
|
||||
/**
|
||||
* Creates a DownloadService which will run in the foreground. {@link
|
||||
* #getForegroundNotification(TaskState[])} should be overridden in the subclass.
|
||||
* #getForegroundNotification(DownloadState[])} should be overridden in the subclass.
|
||||
*
|
||||
* @param foregroundNotificationId The notification id for the foreground notification. Must not
|
||||
* be 0.
|
||||
|
|
@ -338,29 +338,29 @@ public abstract class DownloadService extends Service {
|
|||
*
|
||||
* <p>Returns a notification to be displayed when this service running in the foreground.
|
||||
*
|
||||
* <p>This method is called when there is a task state change and periodically while there are
|
||||
* active tasks. The periodic update interval can be set using {@link #DownloadService(int,
|
||||
* <p>This method is called when there is a download state change and periodically while there are
|
||||
* active downloads. The periodic update interval can be set using {@link #DownloadService(int,
|
||||
* long)}.
|
||||
*
|
||||
* <p>On API level 26 and above, this method may also be called just before the service stops,
|
||||
* with an empty {@code taskStates} array. The returned notification is used to satisfy system
|
||||
* with an empty {@code downloadStates} array. The returned notification is used to satisfy system
|
||||
* requirements for foreground services.
|
||||
*
|
||||
* @param taskStates The states of all current tasks.
|
||||
* @param downloadStates The states of all current downloads.
|
||||
* @return The foreground notification to display.
|
||||
*/
|
||||
protected Notification getForegroundNotification(TaskState[] taskStates) {
|
||||
protected Notification getForegroundNotification(DownloadState[] downloadStates) {
|
||||
throw new IllegalStateException(
|
||||
getClass().getName()
|
||||
+ " is started in the foreground but getForegroundNotification() is not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the state of a task changes.
|
||||
* Called when the state of a download changes.
|
||||
*
|
||||
* @param taskState The state of the task.
|
||||
* @param downloadState The state of the download.
|
||||
*/
|
||||
protected void onTaskStateChanged(TaskState taskState) {
|
||||
protected void onDownloadStateChanged(DownloadState downloadState) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
|
@ -428,10 +428,11 @@ public abstract class DownloadService extends Service {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onTaskStateChanged(DownloadManager downloadManager, TaskState taskState) {
|
||||
DownloadService.this.onTaskStateChanged(taskState);
|
||||
public void onDownloadStateChanged(
|
||||
DownloadManager downloadManager, DownloadState downloadState) {
|
||||
DownloadService.this.onDownloadStateChanged(downloadState);
|
||||
if (foregroundNotificationUpdater != null) {
|
||||
if (taskState.state == TaskState.STATE_STARTED) {
|
||||
if (downloadState.state == DownloadState.STATE_STARTED) {
|
||||
foregroundNotificationUpdater.startPeriodicUpdates();
|
||||
} else {
|
||||
foregroundNotificationUpdater.update();
|
||||
|
|
@ -471,8 +472,8 @@ public abstract class DownloadService extends Service {
|
|||
}
|
||||
|
||||
public void update() {
|
||||
TaskState[] taskStates = downloadManager.getAllTaskStates();
|
||||
startForeground(notificationId, getForegroundNotification(taskStates));
|
||||
DownloadState[] downloadStates = downloadManager.getAllDownloadStates();
|
||||
startForeground(notificationId, getForegroundNotification(downloadStates));
|
||||
notificationDisplayed = true;
|
||||
if (periodicUpdatesStarted) {
|
||||
handler.removeCallbacks(this);
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import android.net.Uri;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState.State;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState.State;
|
||||
import com.google.android.exoplayer2.testutil.DummyMainThread;
|
||||
import com.google.android.exoplayer2.testutil.RobolectricUtil;
|
||||
import com.google.android.exoplayer2.testutil.TestDownloadManagerListener;
|
||||
|
|
@ -371,11 +371,11 @@ public class DownloadManagerTest {
|
|||
TaskWrapper task2 = new DownloadRunner(uri2).postDownloadAction().getTask();
|
||||
TaskWrapper task3 = new DownloadRunner(uri3).postRemoveAction().getTask();
|
||||
|
||||
TaskState[] states = downloadManager.getAllTaskStates();
|
||||
DownloadState[] states = downloadManager.getAllDownloadStates();
|
||||
|
||||
assertThat(states).hasLength(3);
|
||||
int[] taskIds = {task1.taskId, task2.taskId, task3.taskId};
|
||||
int[] stateTaskIds = {states[0].taskId, states[1].taskId, states[2].taskId};
|
||||
int[] stateTaskIds = {states[0].id, states[1].id, states[2].id};
|
||||
assertThat(stateTaskIds).isEqualTo(taskIds);
|
||||
}
|
||||
|
||||
|
|
@ -522,19 +522,19 @@ public class DownloadManagerTest {
|
|||
}
|
||||
|
||||
private TaskWrapper assertStarted() throws InterruptedException {
|
||||
return assertState(TaskState.STATE_STARTED);
|
||||
return assertState(DownloadState.STATE_STARTED);
|
||||
}
|
||||
|
||||
private TaskWrapper assertCompleted() {
|
||||
return assertState(TaskState.STATE_COMPLETED);
|
||||
return assertState(DownloadState.STATE_COMPLETED);
|
||||
}
|
||||
|
||||
private TaskWrapper assertFailed() {
|
||||
return assertState(TaskState.STATE_FAILED);
|
||||
return assertState(DownloadState.STATE_FAILED);
|
||||
}
|
||||
|
||||
private TaskWrapper assertQueued() {
|
||||
return assertState(TaskState.STATE_QUEUED);
|
||||
return assertState(DownloadState.STATE_QUEUED);
|
||||
}
|
||||
|
||||
private TaskWrapper assertState(@State int expectedState) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import android.support.annotation.Nullable;
|
|||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
|
||||
/** Helper for creating download notifications. */
|
||||
public final class DownloadNotificationUtil {
|
||||
|
|
@ -33,7 +33,7 @@ public final class DownloadNotificationUtil {
|
|||
private DownloadNotificationUtil() {}
|
||||
|
||||
/**
|
||||
* Returns a progress notification for the given task states.
|
||||
* Returns a progress notification for the given download states.
|
||||
*
|
||||
* @param context A context for accessing resources.
|
||||
* @param smallIcon A small icon for the notification.
|
||||
|
|
@ -41,7 +41,7 @@ public final class DownloadNotificationUtil {
|
|||
* above.
|
||||
* @param contentIntent An optional content intent to send when the notification is clicked.
|
||||
* @param message An optional message to display on the notification.
|
||||
* @param taskStates The task states.
|
||||
* @param downloadStates The download states.
|
||||
* @return The notification.
|
||||
*/
|
||||
public static Notification buildProgressNotification(
|
||||
|
|
@ -50,28 +50,28 @@ public final class DownloadNotificationUtil {
|
|||
String channelId,
|
||||
@Nullable PendingIntent contentIntent,
|
||||
@Nullable String message,
|
||||
TaskState[] taskStates) {
|
||||
DownloadState[] downloadStates) {
|
||||
float totalPercentage = 0;
|
||||
int downloadTaskCount = 0;
|
||||
boolean allDownloadPercentagesUnknown = true;
|
||||
boolean haveDownloadedBytes = false;
|
||||
boolean haveDownloadTasks = false;
|
||||
boolean haveRemoveTasks = false;
|
||||
for (TaskState taskState : taskStates) {
|
||||
if (taskState.state != TaskState.STATE_STARTED
|
||||
&& taskState.state != TaskState.STATE_COMPLETED) {
|
||||
for (DownloadState downloadState : downloadStates) {
|
||||
if (downloadState.state != DownloadState.STATE_STARTED
|
||||
&& downloadState.state != DownloadState.STATE_COMPLETED) {
|
||||
continue;
|
||||
}
|
||||
if (taskState.action.isRemoveAction) {
|
||||
if (downloadState.action.isRemoveAction) {
|
||||
haveRemoveTasks = true;
|
||||
continue;
|
||||
}
|
||||
haveDownloadTasks = true;
|
||||
if (taskState.downloadPercentage != C.PERCENTAGE_UNSET) {
|
||||
if (downloadState.downloadPercentage != C.PERCENTAGE_UNSET) {
|
||||
allDownloadPercentagesUnknown = false;
|
||||
totalPercentage += taskState.downloadPercentage;
|
||||
totalPercentage += downloadState.downloadPercentage;
|
||||
}
|
||||
haveDownloadedBytes |= taskState.downloadedBytes > 0;
|
||||
haveDownloadedBytes |= downloadState.downloadedBytes > 0;
|
||||
downloadTaskCount++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.android.exoplayer2.offline.DownloadManager;
|
||||
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
|
@ -56,12 +57,11 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onTaskStateChanged(
|
||||
DownloadManager downloadManager, DownloadManager.TaskState taskState) {
|
||||
if (taskState.state == DownloadManager.TaskState.STATE_FAILED && downloadError == null) {
|
||||
downloadError = taskState.error;
|
||||
public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) {
|
||||
if (downloadState.state == DownloadState.STATE_FAILED && downloadError == null) {
|
||||
downloadError = downloadState.error;
|
||||
}
|
||||
getStateQueue(taskState.taskId).add(taskState.state);
|
||||
getStateQueue(downloadState.id).add(downloadState.state);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in a new issue