Fix stopping downloads

- Changed startDownloads/stopDownloads back to their previous behavior
  of starting and stopping all downloads at the manager level.
- Made setManualStopReason methods for the new case of setting a manual
  stop reason or some or all downloads.
- Added plumbing to specify an initial manual stop reason when adding a
  new download, without also overwriting the manual stop reasons of all
  other preexisting downloads. Using the value is left as a TODO pending
  a bit of further cleanup that'll make it easier.

PiperOrigin-RevId: 242891688
This commit is contained in:
olly 2019-04-10 18:15:27 +01:00 committed by Oliver Woodman
parent 68993f233d
commit 9779d71a1d
5 changed files with 198 additions and 180 deletions

View file

@ -46,7 +46,7 @@ public final class Download {
// Important: These constants are persisted into DownloadIndex. Do not change them.
/** The download is waiting to be started. */
public static final int STATE_QUEUED = 0;
/** The download is stopped. */
/** The download is manually stopped for the reason specified by {@link #manualStopReason}. */
public static final int STATE_STOPPED = 1;
/** The download is currently started. */
public static final int STATE_DOWNLOADING = 2;
@ -71,8 +71,6 @@ public final class Download {
/** The download isn't manually stopped. */
public static final int MANUAL_STOP_REASON_NONE = 0;
/** The download is manually stopped but a reason isn't specified. */
public static final int MANUAL_STOP_REASON_UNDEFINED = Integer.MAX_VALUE;
/** Returns the state string for the given state value. */
public static String getStateString(@State int state) {
@ -122,7 +120,7 @@ public final class Download {
* #FAILURE_REASON_NONE}.
*/
@FailureReason public final int failureReason;
/** The manual stop reason. */
/** The reason the download is manually stopped, or {@link #MANUAL_STOP_REASON_NONE}. */
public final int manualStopReason;
/*package*/ CachingCounters counters;
@ -232,7 +230,7 @@ public final class Download {
this.counters = counters;
}
private static int getNextState(int currentState, boolean canStart) {
private static int getNextState(@State int currentState, boolean canStart) {
if (currentState == STATE_REMOVING || currentState == STATE_RESTARTING) {
return STATE_RESTARTING;
} else if (canStart) {

View file

@ -18,7 +18,6 @@ package com.google.android.exoplayer2.offline;
import static com.google.android.exoplayer2.offline.Download.FAILURE_REASON_NONE;
import static com.google.android.exoplayer2.offline.Download.FAILURE_REASON_UNKNOWN;
import static com.google.android.exoplayer2.offline.Download.MANUAL_STOP_REASON_NONE;
import static com.google.android.exoplayer2.offline.Download.MANUAL_STOP_REASON_UNDEFINED;
import static com.google.android.exoplayer2.offline.Download.STATE_COMPLETED;
import static com.google.android.exoplayer2.offline.Download.STATE_DOWNLOADING;
import static com.google.android.exoplayer2.offline.Download.STATE_FAILED;
@ -53,7 +52,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Manages multiple stream download and remove requests.
* Manages downloads.
*
* <p>Normally a download manager should be accessed via a {@link DownloadService}. When a download
* manager is used directly instead, downloads will be initially stopped and so must be started by
* calling {@link #startDownloads()}.
*
* <p>A download manager instance must be accessed only from the thread that created it, unless that
* thread does not have a {@link Looper}. In that case, it must be accessed only from the
@ -122,12 +125,13 @@ public final class DownloadManager {
// Messages posted to the background handler.
private static final int MSG_INITIALIZE = 0;
private static final int MSG_ADD_DOWNLOAD = 1;
private static final int MSG_REMOVE_DOWNLOAD = 2;
private static final int MSG_SET_DOWNLOADS_STARTED = 1;
private static final int MSG_SET_NOT_MET_REQUIREMENTS = 2;
private static final int MSG_SET_MANUAL_STOP_REASON = 3;
private static final int MSG_SET_NOT_MET_REQUIREMENTS = 4;
private static final int MSG_DOWNLOAD_THREAD_STOPPED = 5;
private static final int MSG_RELEASE = 6;
private static final int MSG_ADD_DOWNLOAD = 4;
private static final int MSG_REMOVE_DOWNLOAD = 5;
private static final int MSG_DOWNLOAD_THREAD_STOPPED = 6;
private static final int MSG_RELEASE = 7;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@ -174,7 +178,7 @@ public final class DownloadManager {
// Mutable fields that are accessed on the internal thread.
@Requirements.RequirementFlags private int notMetRequirements;
private int manualStopReason;
private boolean downloadsStarted;
private int simultaneousDownloads;
/**
@ -244,7 +248,6 @@ public final class DownloadManager {
this.maxSimultaneousDownloads = maxSimultaneousDownloads;
this.minRetryCount = minRetryCount;
manualStopReason = MANUAL_STOP_REASON_UNDEFINED;
downloadInternals = new ArrayList<>();
downloads = new ArrayList<>();
activeDownloads = new HashMap<>();
@ -331,63 +334,37 @@ public final class DownloadManager {
}
/**
* Clears manual stop reason of all downloads. Downloads are started if the requirements are met.
* Starts all downloads except those that are manually stopped (i.e. have a non-zero {@link
* Download#manualStopReason}).
*/
public void startDownloads() {
postSetManualStopReason(/* id= */ null, MANUAL_STOP_REASON_NONE);
pendingMessages++;
internalHandler
.obtainMessage(MSG_SET_DOWNLOADS_STARTED, /* downloadsStarted */ 1, /* unused */ 0)
.sendToTarget();
}
/** Signals all downloads to stop. Call {@link #startDownloads()} to let them to be started. */
/** Stops all downloads. */
public void stopDownloads() {
stopDownloads(MANUAL_STOP_REASON_UNDEFINED);
pendingMessages++;
internalHandler
.obtainMessage(MSG_SET_DOWNLOADS_STARTED, /* downloadsStarted */ 0, /* unused */ 0)
.sendToTarget();
}
/**
* Sets a manual stop reason for all downloads.
* Sets the manual stop reason for one or all downloads. To clear the manual stop reason, pass
* {@link Download#MANUAL_STOP_REASON_NONE}.
*
* @param manualStopReason An application defined stop reason. Value {@value
* Download#MANUAL_STOP_REASON_NONE} is not allowed and value {@value
* Download#MANUAL_STOP_REASON_UNDEFINED} is reserved for {@link
* Download#MANUAL_STOP_REASON_UNDEFINED}.
* @param id The content id of the download to update, or {@code null} to set the manual stop
* reason for all downloads.
* @param manualStopReason The manual stop reason, or {@link Download#MANUAL_STOP_REASON_NONE}.
*/
public void stopDownloads(int manualStopReason) {
Assertions.checkArgument(manualStopReason != MANUAL_STOP_REASON_NONE);
postSetManualStopReason(/* id= */ null, manualStopReason);
}
/**
* Clears manual stop reason of the download with the {@code id}. Download is started if the
* requirements are met.
*
* @param id The unique content id of the download to be started.
*/
public void startDownload(String id) {
postSetManualStopReason(id, MANUAL_STOP_REASON_NONE);
}
/**
* Signals the download with the {@code id} to stop. Call {@link #startDownload(String)} to let it
* to be started.
*
* @param id The unique content id of the download to be stopped.
*/
public void stopDownload(String id) {
stopDownload(id, MANUAL_STOP_REASON_UNDEFINED);
}
/**
* Signals the download with the {@code id} to stop. Call {@link #startDownload(String)} to let it
* to be started.
*
* @param id The unique content id of the download to be stopped.
* @param manualStopReason An application defined stop reason. Value {@value
* Download#MANUAL_STOP_REASON_NONE} is not allowed and value {@value
* Download#MANUAL_STOP_REASON_UNDEFINED} is reserved for {@link
* Download#MANUAL_STOP_REASON_UNDEFINED}.
*/
public void stopDownload(String id, int manualStopReason) {
Assertions.checkArgument(manualStopReason != MANUAL_STOP_REASON_NONE);
postSetManualStopReason(id, manualStopReason);
public void setManualStopReason(@Nullable String id, int manualStopReason) {
pendingMessages++;
internalHandler
.obtainMessage(MSG_SET_MANUAL_STOP_REASON, manualStopReason, /* unused */ 0, id)
.sendToTarget();
}
/**
@ -396,8 +373,21 @@ public final class DownloadManager {
* @param action The download action.
*/
public void addDownload(DownloadAction action) {
addDownload(action, Download.MANUAL_STOP_REASON_NONE);
}
/**
* Adds a download defined by the given action and with the specified manual stop reason.
*
* @param action The download action.
* @param manualStopReason An initial manual stop reason for the download, or {@link
* Download#MANUAL_STOP_REASON_NONE} if the download should be started.
*/
public void addDownload(DownloadAction action, int manualStopReason) {
pendingMessages++;
internalHandler.obtainMessage(MSG_ADD_DOWNLOAD, action).sendToTarget();
internalHandler
.obtainMessage(MSG_ADD_DOWNLOAD, manualStopReason, /* unused */ 0, action)
.sendToTarget();
}
/**
@ -442,13 +432,6 @@ public final class DownloadManager {
}
}
private void postSetManualStopReason(@Nullable String id, int manualStopReason) {
pendingMessages++;
internalHandler
.obtainMessage(MSG_SET_MANUAL_STOP_REASON, manualStopReason, /* unused */ 0, id)
.sendToTarget();
}
private void onRequirementsStateChanged(
RequirementsWatcher requirementsWatcher,
@Requirements.RequirementFlags int notMetRequirements) {
@ -551,27 +534,32 @@ public final class DownloadManager {
int notMetRequirements = message.arg1;
initializeInternal(notMetRequirements);
break;
case MSG_ADD_DOWNLOAD:
DownloadAction action = (DownloadAction) message.obj;
addDownloadInternal(action);
break;
case MSG_REMOVE_DOWNLOAD:
String id = (String) message.obj;
removeDownloadInternal(id);
break;
case MSG_SET_MANUAL_STOP_REASON:
id = (String) message.obj;
int manualStopReason = message.arg1;
setManualStopReasonInternal(id, manualStopReason);
case MSG_SET_DOWNLOADS_STARTED:
boolean downloadsStarted = message.arg1 != 0;
setDownloadsStartedInternal(downloadsStarted);
break;
case MSG_SET_NOT_MET_REQUIREMENTS:
notMetRequirements = message.arg1;
setNotMetRequirementsInternal(notMetRequirements);
break;
case MSG_SET_MANUAL_STOP_REASON:
String id = (String) message.obj;
int manualStopReason = message.arg1;
setManualStopReasonInternal(id, manualStopReason);
break;
case MSG_ADD_DOWNLOAD:
DownloadAction action = (DownloadAction) message.obj;
manualStopReason = message.arg1;
addDownloadInternal(action, manualStopReason);
break;
case MSG_REMOVE_DOWNLOAD:
id = (String) message.obj;
removeDownloadInternal(id);
break;
case MSG_DOWNLOAD_THREAD_STOPPED:
DownloadThread downloadThread = (DownloadThread) message.obj;
onDownloadThreadStoppedInternal(downloadThread);
processedExternalMessage = false;
processedExternalMessage = false; // This message is posted internally.
break;
case MSG_RELEASE:
releaseInternal();
@ -594,7 +582,6 @@ public final class DownloadManager {
return;
}
} else {
this.manualStopReason = manualStopReason;
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).setManualStopReason(manualStopReason);
}
@ -610,7 +597,8 @@ public final class DownloadManager {
}
}
private void addDownloadInternal(DownloadAction action) {
// TODO: Use manualStopReason.
private void addDownloadInternal(DownloadAction action, int manualStopReason) {
DownloadInternal downloadInternal = getDownload(action.id);
if (downloadInternal != null) {
downloadInternal.addAction(action);
@ -621,7 +609,7 @@ public final class DownloadManager {
download = new Download(action);
logd("Download state is created for " + action.id);
} else {
download = download.copyWithMergedAction(action, /* canStart= */ notMetRequirements == 0);
download = download.copyWithMergedAction(action, /* canStart= */ canStartDownloads());
logd("Download state is loaded for " + action.id);
}
addDownloadForState(download);
@ -666,6 +654,16 @@ public final class DownloadManager {
mainHandler.obtainMessage(MSG_DOWNLOAD_REMOVED, download).sendToTarget();
}
private void setDownloadsStartedInternal(boolean downloadsStarted) {
if (this.downloadsStarted == downloadsStarted) {
return;
}
this.downloadsStarted = downloadsStarted;
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).updateStopState();
}
}
private void setNotMetRequirementsInternal(
@Requirements.RequirementFlags int notMetRequirements) {
if (this.notMetRequirements == notMetRequirements) {
@ -674,7 +672,7 @@ public final class DownloadManager {
this.notMetRequirements = notMetRequirements;
logdFlags("Not met requirements are changed", notMetRequirements);
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).setNotMetRequirements(notMetRequirements);
downloadInternals.get(i).updateStopState();
}
}
@ -682,7 +680,7 @@ public final class DownloadManager {
private DownloadInternal getDownload(String id) {
for (int i = 0; i < downloadInternals.size(); i++) {
DownloadInternal downloadInternal = downloadInternals.get(i);
if (downloadInternal.getId().equals(id)) {
if (downloadInternal.download.action.id.equals(id)) {
return downloadInternal;
}
}
@ -723,13 +721,16 @@ public final class DownloadManager {
}
private void addDownloadForState(Download download) {
DownloadInternal downloadInternal =
new DownloadInternal(this, download, notMetRequirements, manualStopReason);
DownloadInternal downloadInternal = new DownloadInternal(this, download);
downloadInternals.add(downloadInternal);
logd("Download is added", downloadInternal);
downloadInternal.initialize();
}
private boolean canStartDownloads() {
return downloadsStarted && notMetRequirements == 0;
}
private static void logd(String message) {
if (DEBUG) {
Log.d(TAG, message);
@ -814,32 +815,24 @@ public final class DownloadManager {
private final DownloadManager downloadManager;
private Download download;
@Download.State private int state;
@MonotonicNonNull @Download.FailureReason private int failureReason;
@Requirements.RequirementFlags private int notMetRequirements;
// TODO: Get rid of these and use download directly.
@Download.State private int state;
private int manualStopReason;
private DownloadInternal(
DownloadManager downloadManager,
Download download,
@Requirements.RequirementFlags int notMetRequirements,
int manualStopReason) {
private DownloadInternal(DownloadManager downloadManager, Download download) {
this.downloadManager = downloadManager;
this.download = download;
this.notMetRequirements = notMetRequirements;
this.manualStopReason = manualStopReason;
manualStopReason = download.manualStopReason;
}
private void initialize() {
initialize(download.state);
}
public String getId() {
return download.action.id;
}
public void addAction(DownloadAction newAction) {
download = download.copyWithMergedAction(newAction, /* canStart= */ notMetRequirements == 0);
download = download.copyWithMergedAction(newAction, downloadManager.canStartDownloads());
initialize();
}
@ -866,7 +859,7 @@ public final class DownloadManager {
@Override
public String toString() {
return getId() + ' ' + Download.getStateString(state);
return download.action.id + ' ' + Download.getStateString(state);
}
public void start() {
@ -877,11 +870,6 @@ public final class DownloadManager {
}
}
public void setNotMetRequirements(@Requirements.RequirementFlags int notMetRequirements) {
this.notMetRequirements = notMetRequirements;
updateStopState();
}
public void setManualStopReason(int manualStopReason) {
this.manualStopReason = manualStopReason;
updateStopState();
@ -913,8 +901,8 @@ public final class DownloadManager {
}
private void initialize(int initialState) {
// Don't notify listeners with initial state until we make sure we don't switch to
// another state immediately.
// Don't notify listeners with initial state until we make sure we don't switch to another
// state immediately.
state = initialState;
if (isInRemoveState()) {
downloadManager.startDownloadThread(this);
@ -929,7 +917,7 @@ public final class DownloadManager {
}
private boolean canStart() {
return manualStopReason == MANUAL_STOP_REASON_NONE && notMetRequirements == 0;
return downloadManager.canStartDownloads() && manualStopReason == MANUAL_STOP_REASON_NONE;
}
private void startOrQueue() {

View file

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.offline;
import static com.google.android.exoplayer2.offline.Download.MANUAL_STOP_REASON_NONE;
import android.app.Notification;
import android.app.Service;
import android.content.Context;
@ -55,17 +57,18 @@ public abstract class DownloadService extends Service {
* <ul>
* <li>{@link #KEY_DOWNLOAD_ACTION} - A {@link DownloadAction} defining the download to be
* added.
* <li>{@link #KEY_MANUAL_STOP_REASON} - An initial manual stop reason for the download. If
* omitted {@link Download#MANUAL_STOP_REASON_NONE} is used.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
*/
public static final String ACTION_ADD = "com.google.android.exoplayer.downloadService.action.ADD";
/**
* Starts one or all of the current downloads. Extras:
* Starts all downloads except those that are manually stopped (i.e. have a non-zero {@link
* Download#manualStopReason}). Extras:
*
* <ul>
* <li>{@link #KEY_CONTENT_ID} - The content id of a single download to start. If omitted, all
* of the current downloads will be started.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
*/
@ -73,20 +76,31 @@ public abstract class DownloadService extends Service {
"com.google.android.exoplayer.downloadService.action.START";
/**
* Stops one or all of the current downloads. Extras:
* Stops all downloads. Extras:
*
* <ul>
* <li>{@link #KEY_CONTENT_ID} - The content id of a single download to stop. If omitted, all of
* the current downloads will be stopped.
* <li>{@link #KEY_STOP_REASON} - An application provided reason for stopping the download or
* downloads. Must not be {@link Download#MANUAL_STOP_REASON_NONE}. If omitted, the stop
* reason will be {@link Download#MANUAL_STOP_REASON_UNDEFINED}.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
*/
public static final String ACTION_STOP =
"com.google.android.exoplayer.downloadService.action.STOP";
/**
* Sets the manual stop reason for one or all downloads. To clear the manual stop reason, pass
* {@link Download#MANUAL_STOP_REASON_NONE}. Extras:
*
* <ul>
* <li>{@link #KEY_CONTENT_ID} - The content id of a single download to update with the manual
* stop reason. If omitted, all downloads will be updated.
* <li>{@link #KEY_MANUAL_STOP_REASON} - An application provided reason for stopping the
* download or downloads, or {@link Download#MANUAL_STOP_REASON_NONE} to clear the manual
* stop reason.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
*/
public static final String ACTION_SET_MANUAL_STOP_REASON =
"com.google.android.exoplayer.downloadService.action.SET_MANUAL_STOP_REASON";
/**
* Removes an existing download. Extras:
*
@ -110,8 +124,11 @@ public abstract class DownloadService extends Service {
*/
public static final String KEY_CONTENT_ID = "content_id";
/** Key for the stop reason in {@link #ACTION_STOP} intents. */
public static final String KEY_STOP_REASON = "stop_reason";
/**
* Key for the manual stop reason in {@link #ACTION_SET_MANUAL_STOP_REASON} and {@link
* #ACTION_ADD} intents.
*/
public static final String KEY_MANUAL_STOP_REASON = "manual_stop_reason";
/**
* Key for a boolean extra that can be set on any intent to indicate whether the service was
@ -228,43 +245,31 @@ public abstract class DownloadService extends Service {
Class<? extends DownloadService> clazz,
DownloadAction downloadAction,
boolean foreground) {
return getIntent(context, clazz, ACTION_ADD)
.putExtra(KEY_DOWNLOAD_ACTION, downloadAction)
.putExtra(KEY_FOREGROUND, foreground);
return buildAddActionIntent(
context, clazz, downloadAction, MANUAL_STOP_REASON_NONE, foreground);
}
/**
* Builds an {@link Intent} for stopping the download with the {@code id}. If {@code id} is null,
* stops all downloads.
* Builds an {@link Intent} for adding an action to be executed by the service.
*
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id, or null if all downloads should be stopped.
* @param manualStopReason An application defined stop reason.
* @param downloadAction The action to be executed.
* @param manualStopReason An initial manual stop reason for the download, or {@link
* Download#MANUAL_STOP_REASON_NONE} if the download should be started.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return Created Intent.
*/
public static Intent buildStopDownloadIntent(
public static Intent buildAddActionIntent(
Context context,
Class<? extends DownloadService> clazz,
@Nullable String id,
int manualStopReason) {
return getIntent(context, clazz, ACTION_STOP)
.putExtra(KEY_CONTENT_ID, id)
.putExtra(KEY_STOP_REASON, manualStopReason);
}
/**
* Builds an {@link Intent} for starting the download with the {@code id}. If {@code id} is null,
* starts all downloads.
*
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id, or null if all downloads should be started.
* @return Created Intent.
*/
public static Intent buildStartDownloadIntent(
Context context, Class<? extends DownloadService> clazz, @Nullable String id) {
return getIntent(context, clazz, ACTION_START).putExtra(KEY_CONTENT_ID, id);
DownloadAction downloadAction,
int manualStopReason,
boolean foreground) {
return getIntent(context, clazz, ACTION_ADD)
.putExtra(KEY_DOWNLOAD_ACTION, downloadAction)
.putExtra(KEY_MANUAL_STOP_REASON, manualStopReason)
.putExtra(KEY_FOREGROUND, foreground);
}
/**
@ -283,6 +288,26 @@ public abstract class DownloadService extends Service {
.putExtra(KEY_FOREGROUND, foreground);
}
/**
* Builds an {@link Intent} for setting the manual stop reason for one or all downloads. To clear
* the manual stop reason, pass {@link Download#MANUAL_STOP_REASON_NONE}.
*
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id, or {@code null} to set the manual stop reason for all downloads.
* @param manualStopReason An application defined stop reason.
* @return Created Intent.
*/
public static Intent buildSetManualStopReasonIntent(
Context context,
Class<? extends DownloadService> clazz,
@Nullable String id,
int manualStopReason) {
return getIntent(context, clazz, ACTION_STOP)
.putExtra(KEY_CONTENT_ID, id)
.putExtra(KEY_MANUAL_STOP_REASON, manualStopReason);
}
/**
* Starts the service, adding an action to be executed.
*
@ -358,9 +383,11 @@ public abstract class DownloadService extends Service {
Class<? extends DownloadService> clazz = getClass();
DownloadManagerHelper downloadManagerHelper = downloadManagerListeners.get(clazz);
if (downloadManagerHelper == null) {
DownloadManager downloadManager = getDownloadManager();
downloadManager.startDownloads();
downloadManagerHelper =
new DownloadManagerHelper(
getApplicationContext(), getDownloadManager(), getScheduler(), clazz);
getApplicationContext(), downloadManager, getScheduler(), clazz);
downloadManagerListeners.put(clazz, downloadManagerHelper);
}
downloadManager = downloadManagerHelper.downloadManager;
@ -390,32 +417,33 @@ public abstract class DownloadService extends Service {
case ACTION_ADD:
DownloadAction downloadAction = intent.getParcelableExtra(KEY_DOWNLOAD_ACTION);
if (downloadAction == null) {
Log.e(TAG, "Ignored ADD action: Missing download_action extra");
Log.e(TAG, "Ignored ADD: Missing download_action extra");
} else {
downloadManager.addDownload(downloadAction);
int manualStopReason =
intent.getIntExtra(KEY_MANUAL_STOP_REASON, Download.MANUAL_STOP_REASON_NONE);
downloadManager.addDownload(downloadAction, manualStopReason);
}
break;
case ACTION_START:
String contentId = intent.getStringExtra(KEY_CONTENT_ID);
if (contentId == null) {
downloadManager.startDownloads();
} else {
downloadManager.startDownload(contentId);
}
downloadManager.startDownloads();
break;
case ACTION_STOP:
contentId = intent.getStringExtra(KEY_CONTENT_ID);
int stopReason = intent.getIntExtra(KEY_STOP_REASON, Download.MANUAL_STOP_REASON_UNDEFINED);
if (contentId == null) {
downloadManager.stopDownloads(stopReason);
downloadManager.stopDownloads();
break;
case ACTION_SET_MANUAL_STOP_REASON:
if (!intent.hasExtra(KEY_MANUAL_STOP_REASON)) {
Log.e(TAG, "Ignored SET_MANUAL_STOP_REASON: Missing manual_stop_reason extra");
} else {
downloadManager.stopDownload(contentId, stopReason);
String contentId = intent.getStringExtra(KEY_CONTENT_ID);
int manualStopReason =
intent.getIntExtra(KEY_MANUAL_STOP_REASON, Download.MANUAL_STOP_REASON_NONE);
downloadManager.setManualStopReason(contentId, manualStopReason);
}
break;
case ACTION_REMOVE:
contentId = intent.getStringExtra(KEY_CONTENT_ID);
String contentId = intent.getStringExtra(KEY_CONTENT_ID);
if (contentId == null) {
Log.e(TAG, "Ignored REMOVE action: Missing content_id extra");
Log.e(TAG, "Ignored REMOVE: Missing content_id extra");
} else {
downloadManager.removeDownload(contentId);
}

View file

@ -47,14 +47,16 @@ import org.robolectric.shadows.ShadowLog;
@Config(shadows = {RobolectricUtil.CustomLooper.class, RobolectricUtil.CustomMessageQueue.class})
public class DownloadManagerTest {
/* Used to check if condition becomes true in this time interval. */
/** Used to check if condition becomes true in this time interval. */
private static final int ASSERT_TRUE_TIMEOUT = 10000;
/* Used to check if condition stays false for this time interval. */
/** Used to check if condition stays false for this time interval. */
private static final int ASSERT_FALSE_TIME = 1000;
/* Maximum retry delay in DownloadManager. */
/** Maximum retry delay in DownloadManager. */
private static final int MAX_RETRY_DELAY = 5000;
/* Maximum number of times a downloader can be restarted before doing a released check. */
/** Maximum number of times a downloader can be restarted before doing a released check. */
private static final int MAX_STARTS_BEFORE_RELEASED = 1;
/** A manual stop reason. */
private static final int APP_STOP_REASON = 1;
/** The minimum number of times a task must be retried before failing. */
private static final int MIN_RETRY_COUNT = 3;
@ -388,17 +390,18 @@ public class DownloadManagerTest {
}
@Test
public void stopAndResumeSingleDownload() throws Throwable {
public void manuallyStopAndResumeSingleDownload() throws Throwable {
DownloadRunner runner = new DownloadRunner(uri1).postDownloadAction();
TaskWrapper task = runner.getTask();
task.assertDownloading();
runOnMainThread(() -> downloadManager.stopDownload(task.taskId));
runOnMainThread(() -> downloadManager.setManualStopReason(task.taskId, APP_STOP_REASON));
task.assertStopped();
runOnMainThread(() -> downloadManager.startDownload(task.taskId));
runOnMainThread(
() -> downloadManager.setManualStopReason(task.taskId, Download.MANUAL_STOP_REASON_NONE));
runner.getDownloader(1).assertStarted().unblock();
@ -406,13 +409,13 @@ public class DownloadManagerTest {
}
@Test
public void stoppedDownloadCanBeCancelled() throws Throwable {
public void manuallyStoppedDownloadCanBeCancelled() throws Throwable {
DownloadRunner runner = new DownloadRunner(uri1).postDownloadAction();
TaskWrapper task = runner.getTask();
task.assertDownloading();
runOnMainThread(() -> downloadManager.stopDownload(task.taskId));
runOnMainThread(() -> downloadManager.setManualStopReason(task.taskId, APP_STOP_REASON));
task.assertStopped();
@ -424,7 +427,7 @@ public class DownloadManagerTest {
}
@Test
public void stoppedSingleDownload_doesNotAffectOthers() throws Throwable {
public void manuallyStoppedSingleDownload_doesNotAffectOthers() throws Throwable {
DownloadRunner runner1 = new DownloadRunner(uri1);
DownloadRunner runner2 = new DownloadRunner(uri2);
DownloadRunner runner3 = new DownloadRunner(uri3);
@ -432,7 +435,8 @@ public class DownloadManagerTest {
runner1.postDownloadAction().getTask().assertDownloading();
runner2.postDownloadAction().postRemoveAction().getTask().assertRemoving();
runOnMainThread(() -> downloadManager.stopDownload(runner1.getTask().taskId));
runOnMainThread(
() -> downloadManager.setManualStopReason(runner1.getTask().taskId, APP_STOP_REASON));
runner1.getTask().assertStopped();
@ -460,9 +464,9 @@ public class DownloadManagerTest {
maxActiveDownloadTasks,
MIN_RETRY_COUNT,
new Requirements(0));
downloadManager.startDownloads();
downloadManagerListener =
new TestDownloadManagerListener(downloadManager, dummyMainThread);
downloadManager.startDownloads();
});
downloadManagerListener.waitUntilInitialized();
} catch (Throwable throwable) {

View file

@ -156,7 +156,7 @@ public class DownloadTest {
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_STOPPED)
.setManualStopReason(Download.MANUAL_STOP_REASON_UNDEFINED);
.setManualStopReason(/* manualStopReason= */ 1);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
@ -170,7 +170,7 @@ public class DownloadTest {
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_COMPLETED)
.setManualStopReason(Download.MANUAL_STOP_REASON_UNDEFINED);
.setManualStopReason(/* manualStopReason= */ 1);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);