diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java index b3f1d3da6a..4636552a77 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java @@ -773,7 +773,7 @@ public final class DownloadManager { private void stop() { if (changeStateAndNotify(STATE_STARTED, STATE_STARTED_STOPPING)) { logd("Stopping", this); - thread.interrupt(); + cancelDownload(); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java index 6dae3f70b3..0fce96d52f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java @@ -44,6 +44,10 @@ public abstract class DownloadService extends Service { /** Starts a download service, adding a new {@link DownloadAction} to be executed. */ public static final String ACTION_ADD = "com.google.android.exoplayer.downloadService.action.ADD"; + /** Reloads the download requirements. */ + public static final String ACTION_RELOAD_REQUIREMENTS = + "com.google.android.exoplayer.downloadService.action.RELOAD_REQUIREMENTS"; + /** Like {@link #ACTION_INIT}, but with {@link #KEY_FOREGROUND} implicitly set to true. */ private static final String ACTION_RESTART = "com.google.android.exoplayer.downloadService.action.RESTART"; @@ -150,8 +154,7 @@ public abstract class DownloadService extends Service { Class clazz, DownloadAction downloadAction, boolean foreground) { - return new Intent(context, clazz) - .setAction(ACTION_ADD) + return getIntent(context, clazz, ACTION_ADD) .putExtra(KEY_DOWNLOAD_ACTION, downloadAction.toByteArray()) .putExtra(KEY_FOREGROUND, foreground); } @@ -186,7 +189,7 @@ public abstract class DownloadService extends Service { * @see #startForeground(Context, Class) */ public static void start(Context context, Class clazz) { - context.startService(new Intent(context, clazz).setAction(ACTION_INIT)); + context.startService(getIntent(context, clazz, ACTION_INIT)); } /** @@ -199,8 +202,7 @@ public abstract class DownloadService extends Service { * @see #start(Context, Class) */ public static void startForeground(Context context, Class clazz) { - Intent intent = - new Intent(context, clazz).setAction(ACTION_INIT).putExtra(KEY_FOREGROUND, true); + Intent intent = getIntent(context, clazz, ACTION_INIT).putExtra(KEY_FOREGROUND, true); Util.startForegroundService(context, intent); } @@ -249,6 +251,10 @@ public abstract class DownloadService extends Service { case ACTION_START_DOWNLOADS: downloadManager.startDownloads(); break; + case ACTION_RELOAD_REQUIREMENTS: + stopWatchingRequirements(); + maybeStartWatchingRequirements(); + break; default: Log.e(TAG, "Ignoring unrecognized action: " + intentAction); break; @@ -340,6 +346,10 @@ public abstract class DownloadService extends Service { if (downloadManager.getDownloadCount() > 0) { return; } + stopWatchingRequirements(); + } + + private void stopWatchingRequirements() { RequirementsHelper requirementsHelper = requirementsHelpers.remove(getClass()); if (requirementsHelper != null) { requirementsHelper.stop(); @@ -363,6 +373,11 @@ public abstract class DownloadService extends Service { } } + private static Intent getIntent( + Context context, Class clazz, String action) { + return new Intent(context, clazz).setAction(action); + } + private final class DownloadManagerListener implements DownloadManager.Listener { @Override public void onInitialized(DownloadManager downloadManager) { @@ -484,8 +499,7 @@ public abstract class DownloadService extends Service { } private void startServiceWithAction(String action) { - Intent intent = - new Intent(context, serviceClass).setAction(action).putExtra(KEY_FOREGROUND, true); + Intent intent = getIntent(context, serviceClass, action).putExtra(KEY_FOREGROUND, true); Util.startForegroundService(context, intent); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java index 8337f27595..5db4f20ca2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java @@ -195,9 +195,7 @@ public final class CacheUtil { long start = dataSpec.absoluteStreamPosition; long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); while (left != 0) { - if (isCanceled != null && isCanceled.get()) { - throw new InterruptedException(); - } + throwExceptionIfInterruptedOrCancelled(isCanceled); long blockLength = cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); if (blockLength > 0) { @@ -205,8 +203,17 @@ public final class CacheUtil { } else { // There is a hole in the cache which is at least "-blockLength" long. blockLength = -blockLength; - long read = readAndDiscard(dataSpec, start, blockLength, dataSource, buffer, - priorityTaskManager, priority, counters); + long read = + readAndDiscard( + dataSpec, + start, + blockLength, + dataSource, + buffer, + priorityTaskManager, + priority, + counters, + isCanceled); if (read < blockLength) { // Reached to the end of the data. if (enableEOFException && left != C.LENGTH_UNSET) { @@ -233,21 +240,28 @@ public final class CacheUtil { * caching. * @param priority The priority of this task. * @param counters Counters to be set during reading. + * @param isCanceled An optional flag that will interrupt caching if set to true. * @return Number of read bytes, or 0 if no data is available because the end of the opened range * has been reached. */ - private static long readAndDiscard(DataSpec dataSpec, long absoluteStreamPosition, long length, - DataSource dataSource, byte[] buffer, PriorityTaskManager priorityTaskManager, int priority, - CachingCounters counters) throws IOException, InterruptedException { + private static long readAndDiscard( + DataSpec dataSpec, + long absoluteStreamPosition, + long length, + DataSource dataSource, + byte[] buffer, + PriorityTaskManager priorityTaskManager, + int priority, + CachingCounters counters, + AtomicBoolean isCanceled) + throws IOException, InterruptedException { while (true) { if (priorityTaskManager != null) { // Wait for any other thread with higher priority to finish its job. priorityTaskManager.proceed(priority); } try { - if (Thread.interrupted()) { - throw new InterruptedException(); - } + throwExceptionIfInterruptedOrCancelled(isCanceled); // Create a new dataSpec setting length to C.LENGTH_UNSET to prevent getting an error in // case the given length exceeds the end of input. dataSpec = new DataSpec(dataSpec.uri, dataSpec.postBody, absoluteStreamPosition, @@ -260,9 +274,7 @@ public final class CacheUtil { } long totalRead = 0; while (totalRead != length) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } + throwExceptionIfInterruptedOrCancelled(isCanceled); int read = dataSource.read(buffer, 0, length != C.LENGTH_UNSET ? (int) Math.min(buffer.length, length - totalRead) : buffer.length); @@ -296,6 +308,13 @@ public final class CacheUtil { } } + private static void throwExceptionIfInterruptedOrCancelled(AtomicBoolean isCanceled) + throws InterruptedException { + if (Thread.interrupted() || (isCanceled != null && isCanceled.get())) { + throw new InterruptedException(); + } + } + private CacheUtil() {} } diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java index 31f86af115..ce9ba34a18 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java @@ -30,7 +30,6 @@ import com.google.android.exoplayer2.offline.DownloadManager.TaskState; import com.google.android.exoplayer2.offline.DownloadService; import com.google.android.exoplayer2.offline.DownloaderConstructorHelper; import com.google.android.exoplayer2.offline.StreamKey; -import com.google.android.exoplayer2.scheduler.Requirements; import com.google.android.exoplayer2.scheduler.Scheduler; import com.google.android.exoplayer2.testutil.DummyMainThread; import com.google.android.exoplayer2.testutil.FakeDataSet; @@ -152,12 +151,6 @@ public class DownloadServiceDashTest { protected Scheduler getScheduler() { return null; } - - @Nullable - @Override - protected Requirements getRequirements() { - return null; - } }; dashDownloadService.onCreate(); }