Commit 7ae76837 by eguven Committed by Oliver Woodman

Prepare DownloadState for upcoming changes

Made DownloadState top level class.
Replaced action field DownloadAction fields.
Added removing, removed and restarting states.
Renamed started state to downloading.

PiperOrigin-RevId: 227664735
parent 803b878a
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
* DownloadManager: * DownloadManager:
* Create only one task for all DownloadActions for the same content. * Create only one task for all DownloadActions for the same content.
* Rename TaskState to DownloadState. * Rename TaskState to DownloadState.
* Add new states to DownloadState.
* Replace DownloadState.action with DownloadAction fields.
* Add support for SHOUTcast ICY metadata * Add support for SHOUTcast ICY metadata
([#3735](https://github.com/google/ExoPlayer/issues/3735)). ([#3735](https://github.com/google/ExoPlayer/issues/3735)).
* IMA extension: Clear ads loader listeners on release * IMA extension: Clear ads loader listeners on release
......
...@@ -17,8 +17,8 @@ package com.google.android.exoplayer2.demo; ...@@ -17,8 +17,8 @@ package com.google.android.exoplayer2.demo;
import android.app.Notification; import android.app.Notification;
import com.google.android.exoplayer2.offline.DownloadManager; import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
import com.google.android.exoplayer2.offline.DownloadService; import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.scheduler.PlatformScheduler; import com.google.android.exoplayer2.scheduler.PlatformScheduler;
import com.google.android.exoplayer2.ui.DownloadNotificationUtil; import com.google.android.exoplayer2.ui.DownloadNotificationUtil;
import com.google.android.exoplayer2.util.NotificationUtil; import com.google.android.exoplayer2.util.NotificationUtil;
...@@ -65,9 +65,6 @@ public class DemoDownloadService extends DownloadService { ...@@ -65,9 +65,6 @@ public class DemoDownloadService extends DownloadService {
@Override @Override
protected void onDownloadStateChanged(DownloadState downloadState) { protected void onDownloadStateChanged(DownloadState downloadState) {
if (downloadState.action.isRemoveAction) {
return;
}
Notification notification = null; Notification notification = null;
if (downloadState.state == DownloadState.STATE_COMPLETED) { if (downloadState.state == DownloadState.STATE_COMPLETED) {
notification = notification =
...@@ -76,7 +73,7 @@ public class DemoDownloadService extends DownloadService { ...@@ -76,7 +73,7 @@ public class DemoDownloadService extends DownloadService {
R.drawable.ic_download_done, R.drawable.ic_download_done,
CHANNEL_ID, CHANNEL_ID,
/* contentIntent= */ null, /* contentIntent= */ null,
Util.fromUtf8Bytes(downloadState.action.data)); Util.fromUtf8Bytes(downloadState.customMetadata));
} else if (downloadState.state == DownloadState.STATE_FAILED) { } else if (downloadState.state == DownloadState.STATE_FAILED) {
notification = notification =
DownloadNotificationUtil.buildDownloadFailedNotification( DownloadNotificationUtil.buildDownloadFailedNotification(
...@@ -84,7 +81,7 @@ public class DemoDownloadService extends DownloadService { ...@@ -84,7 +81,7 @@ public class DemoDownloadService extends DownloadService {
R.drawable.ic_download_done, R.drawable.ic_download_done,
CHANNEL_ID, CHANNEL_ID,
/* contentIntent= */ null, /* contentIntent= */ null,
Util.fromUtf8Bytes(downloadState.action.data)); Util.fromUtf8Bytes(downloadState.customMetadata));
} else { } else {
return; return;
} }
......
...@@ -37,8 +37,8 @@ import com.google.android.exoplayer2.offline.ActionFile; ...@@ -37,8 +37,8 @@ import com.google.android.exoplayer2.offline.ActionFile;
import com.google.android.exoplayer2.offline.DownloadAction; import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.DownloadManager; import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
import com.google.android.exoplayer2.offline.DownloadService; import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.ProgressiveDownloadHelper; import com.google.android.exoplayer2.offline.ProgressiveDownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
...@@ -145,12 +145,10 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -145,12 +145,10 @@ public class DownloadTracker implements DownloadManager.Listener {
@Override @Override
public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) { public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) {
DownloadAction action = downloadState.action; if (downloadState.state == DownloadState.STATE_REMOVED
Uri uri = action.uri; || downloadState.state == DownloadState.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. // A download has been removed, or has failed. Stop tracking it.
if (trackedDownloadStates.remove(uri) != null) { if (trackedDownloadStates.remove(downloadState.uri) != null) {
handleTrackedDownloadStatesChanged(); handleTrackedDownloadStatesChanged();
} }
} }
......
...@@ -15,29 +15,28 @@ ...@@ -15,29 +15,28 @@
*/ */
package com.google.android.exoplayer2.offline; package com.google.android.exoplayer2.offline;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.FAILURE_REASON_NONE; import static com.google.android.exoplayer2.offline.DownloadState.FAILURE_REASON_NONE;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.FAILURE_REASON_UNKNOWN; import static com.google.android.exoplayer2.offline.DownloadState.FAILURE_REASON_UNKNOWN;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_COMPLETED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_COMPLETED;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_FAILED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_DOWNLOADING;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_QUEUED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_FAILED;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STARTED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_QUEUED;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STATE_STOPPED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_REMOVED;
import static com.google.android.exoplayer2.offline.DownloadManager.DownloadState.STOP_FLAG_STOPPED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_REMOVING;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_RESTARTING;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_STOPPED;
import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_STOPPED;
import android.os.ConditionVariable; import android.os.ConditionVariable;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
...@@ -426,133 +425,6 @@ public final class DownloadManager { ...@@ -426,133 +425,6 @@ public final class DownloadManager {
logd(message + ": " + download); logd(message + ": " + download);
} }
/** Represents state of a download. */
public static final class DownloadState {
/**
* Download states. One of {@link #STATE_QUEUED}, {@link #STATE_STOPPED}, {@link #STATE_STARTED}
* , {@link #STATE_COMPLETED} or {@link #STATE_FAILED}.
*
* <p>Transition diagram:
*
* <pre>
* queued ←┬→ started ┬→ completed
* └→ stopped └→ failed
* </pre>
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({STATE_QUEUED, STATE_STOPPED, STATE_STARTED, STATE_COMPLETED, STATE_FAILED})
public @interface State {}
/** The download is waiting to be started. */
public static final int STATE_QUEUED = 0;
/** The download is stopped. */
public static final int STATE_STOPPED = 1;
/** The download is currently started. */
public static final int STATE_STARTED = 2;
/** The download completed. */
public static final int STATE_COMPLETED = 3;
/** The download failed. */
public static final int STATE_FAILED = 4;
/** Failure reasons. Either {@link #FAILURE_REASON_NONE} or {@link #FAILURE_REASON_UNKNOWN}. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({FAILURE_REASON_NONE, FAILURE_REASON_UNKNOWN})
public @interface FailureReason {}
/** The download isn't failed. */
public static final int FAILURE_REASON_NONE = 0;
/** The download is failed because of unknown reason. */
public static final int FAILURE_REASON_UNKNOWN = 1;
/** Download stop flags. Possible flag value is {@link #STOP_FLAG_STOPPED}. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
value = {STOP_FLAG_STOPPED})
public @interface StopFlags {}
/** All downloads are stopped by the application. */
public static final int STOP_FLAG_STOPPED = 1;
/** Returns the state string for the given state value. */
public static String getStateString(@State int state) {
switch (state) {
case STATE_QUEUED:
return "QUEUED";
case STATE_STOPPED:
return "STOPPED";
case STATE_STARTED:
return "STARTED";
case STATE_COMPLETED:
return "COMPLETED";
case STATE_FAILED:
return "FAILED";
default:
throw new IllegalStateException();
}
}
/** Returns the failure string for the given failure reason value. */
public static String getFailureString(@FailureReason int failureReason) {
switch (failureReason) {
case FAILURE_REASON_NONE:
return "NO_REASON";
case FAILURE_REASON_UNKNOWN:
return "UNKNOWN_REASON";
default:
throw new IllegalStateException();
}
}
/** The unique content id. */
public final String id;
/** The action being executed. */
public final DownloadAction action;
/** The state of the download. */
public final @State int state;
/** The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if unavailable. */
public final float downloadPercentage;
/** The total number of downloaded bytes. */
public final long downloadedBytes;
/** The total size of the media, or {@link C#LENGTH_UNSET} if unknown. */
public final long totalBytes;
/** The first time when download entry is created. */
public final long startTimeMs;
/** The last update time. */
public final long updateTimeMs;
/**
* If {@link #state} is {@link #STATE_FAILED} then this is the cause, otherwise {@link
* #FAILURE_REASON_NONE}.
*/
@FailureReason public final int failureReason;
/** Download stop flags. These flags stop downloading any content. */
@StopFlags public final int stopFlags;
private DownloadState(
DownloadAction action,
@State int state,
float downloadPercentage,
long downloadedBytes,
long totalBytes,
@FailureReason int failureReason,
@StopFlags int stopFlags,
long startTimeMs) {
this.stopFlags = stopFlags;
Assertions.checkState(
failureReason == FAILURE_REASON_NONE ? state != STATE_FAILED : state == STATE_FAILED);
this.id = action.id;
this.action = action;
this.state = state;
this.downloadPercentage = downloadPercentage;
this.downloadedBytes = downloadedBytes;
this.totalBytes = totalBytes;
this.failureReason = failureReason;
this.startTimeMs = startTimeMs;
updateTimeMs = System.currentTimeMillis();
}
}
private static final class Download { private static final class Download {
private final String id; private final String id;
...@@ -601,7 +473,7 @@ public final class DownloadManager { ...@@ -601,7 +473,7 @@ public final class DownloadManager {
if (action.equals(updatedAction)) { if (action.equals(updatedAction)) {
return; return;
} }
if (state == STATE_STARTED) { if (state == STATE_DOWNLOADING) {
stopDownloadThread(); stopDownloadThread();
} else { } else {
Assertions.checkState(state == STATE_QUEUED || state == STATE_STOPPED); Assertions.checkState(state == STATE_QUEUED || state == STATE_STOPPED);
...@@ -618,15 +490,29 @@ public final class DownloadManager { ...@@ -618,15 +490,29 @@ public final class DownloadManager {
downloadedBytes = downloader.getDownloadedBytes(); downloadedBytes = downloader.getDownloadedBytes();
totalBytes = downloader.getTotalBytes(); totalBytes = downloader.getTotalBytes();
} }
int newState = state;
if (action.isRemoveAction) {
if (state == STATE_DOWNLOADING) {
newState = actionQueue.size() > 1 ? STATE_RESTARTING : STATE_REMOVING;
} else if (state == STATE_COMPLETED || state == STATE_FAILED) {
newState = STATE_REMOVED;
}
}
return new DownloadState( return new DownloadState(
action, action.id,
state, action.type,
action.uri,
action.customCacheKey,
newState,
downloadPercentage, downloadPercentage,
downloadedBytes, downloadedBytes,
totalBytes, totalBytes,
failureReason, failureReason,
stopFlags, stopFlags,
startTimeMs); startTimeMs,
/* updateTimeMs= */ System.currentTimeMillis(),
action.keys.toArray(new StreamKey[0]),
action.data);
} }
/** Returns whether the download is finished. */ /** Returns whether the download is finished. */
...@@ -636,7 +522,7 @@ public final class DownloadManager { ...@@ -636,7 +522,7 @@ public final class DownloadManager {
/** Returns whether the download is started. */ /** Returns whether the download is started. */
public boolean isStarted() { public boolean isStarted() {
return state == STATE_STARTED; return state == STATE_DOWNLOADING;
} }
@Override @Override
...@@ -653,7 +539,7 @@ public final class DownloadManager { ...@@ -653,7 +539,7 @@ public final class DownloadManager {
downloadThread = downloadThread =
new DownloadThread( new DownloadThread(
this, downloader, action.isRemoveAction, minRetryCount, downloadManager.handler); this, downloader, action.isRemoveAction, minRetryCount, downloadManager.handler);
setState(STATE_STARTED); setState(STATE_DOWNLOADING);
return true; return true;
} }
...@@ -666,7 +552,7 @@ public final class DownloadManager { ...@@ -666,7 +552,7 @@ public final class DownloadManager {
} }
public void queue() { public void queue() {
if (state == STATE_STARTED) { if (state == STATE_DOWNLOADING) {
stopDownloadThread(); stopDownloadThread();
} }
} }
...@@ -675,7 +561,7 @@ public final class DownloadManager { ...@@ -675,7 +561,7 @@ public final class DownloadManager {
stopFlags = (flags & mask) | (stopFlags & ~mask); stopFlags = (flags & mask) | (stopFlags & ~mask);
if (stopFlags != 0) { if (stopFlags != 0) {
if (!action.isRemoveAction) { if (!action.isRemoveAction) {
if (state == STATE_STARTED) { if (state == STATE_DOWNLOADING) {
stopDownloadThread(); stopDownloadThread();
} else if (state == STATE_QUEUED) { } else if (state == STATE_QUEUED) {
setState(STATE_STOPPED); setState(STATE_STOPPED);
......
...@@ -24,7 +24,6 @@ import android.os.IBinder; ...@@ -24,7 +24,6 @@ import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState;
import com.google.android.exoplayer2.scheduler.Requirements; import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.scheduler.RequirementsWatcher; import com.google.android.exoplayer2.scheduler.RequirementsWatcher;
import com.google.android.exoplayer2.scheduler.Scheduler; import com.google.android.exoplayer2.scheduler.Scheduler;
...@@ -432,7 +431,9 @@ public abstract class DownloadService extends Service { ...@@ -432,7 +431,9 @@ public abstract class DownloadService extends Service {
DownloadManager downloadManager, DownloadState downloadState) { DownloadManager downloadManager, DownloadState downloadState) {
DownloadService.this.onDownloadStateChanged(downloadState); DownloadService.this.onDownloadStateChanged(downloadState);
if (foregroundNotificationUpdater != null) { if (foregroundNotificationUpdater != null) {
if (downloadState.state == DownloadState.STATE_STARTED) { if (downloadState.state == DownloadState.STATE_DOWNLOADING
|| downloadState.state == DownloadState.STATE_REMOVING
|| downloadState.state == DownloadState.STATE_RESTARTING) {
foregroundNotificationUpdater.startPeriodicUpdates(); foregroundNotificationUpdater.startPeriodicUpdates();
} else { } else {
foregroundNotificationUpdater.update(); foregroundNotificationUpdater.update();
......
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.offline;
import android.net.Uri;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** Represents state of a download. */
public final class DownloadState {
/**
* Download states. One of {@link #STATE_QUEUED}, {@link #STATE_STOPPED}, {@link
* #STATE_DOWNLOADING}, {@link #STATE_COMPLETED}, {@link #STATE_FAILED}, {@link #STATE_REMOVING},
* {@link #STATE_REMOVED} or {@link #STATE_RESTARTING}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({
STATE_QUEUED,
STATE_STOPPED,
STATE_DOWNLOADING,
STATE_COMPLETED,
STATE_FAILED,
STATE_REMOVING,
STATE_REMOVED,
STATE_RESTARTING
})
public @interface State {}
/** The download is waiting to be started. */
public static final int STATE_QUEUED = 0;
/** The download is stopped. */
public static final int STATE_STOPPED = 1;
/** The download is currently started. */
public static final int STATE_DOWNLOADING = 2;
/** The download completed. */
public static final int STATE_COMPLETED = 3;
/** The download failed. */
public static final int STATE_FAILED = 4;
/** The download is being removed. */
public static final int STATE_REMOVING = 5;
/** The download is removed. */
public static final int STATE_REMOVED = 6;
/** The download will restart after all downloaded data is removed. */
public static final int STATE_RESTARTING = 7;
/** Failure reasons. Either {@link #FAILURE_REASON_NONE} or {@link #FAILURE_REASON_UNKNOWN}. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({FAILURE_REASON_NONE, FAILURE_REASON_UNKNOWN})
public @interface FailureReason {}
/** The download isn't failed. */
public static final int FAILURE_REASON_NONE = 0;
/** The download is failed because of unknown reason. */
public static final int FAILURE_REASON_UNKNOWN = 1;
/** Download stop flags. Possible flag value is {@link #STOP_FLAG_STOPPED}. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
value = {STOP_FLAG_STOPPED})
public @interface StopFlags {}
/** All downloads are stopped by the application. */
public static final int STOP_FLAG_STOPPED = 1;
/** Returns the state string for the given state value. */
public static String getStateString(@State int state) {
switch (state) {
case STATE_QUEUED:
return "QUEUED";
case STATE_STOPPED:
return "STOPPED";
case STATE_DOWNLOADING:
return "DOWNLOADING";
case STATE_COMPLETED:
return "COMPLETED";
case STATE_FAILED:
return "FAILED";
case STATE_REMOVING:
return "REMOVING";
case STATE_REMOVED:
return "REMOVED";
case STATE_RESTARTING:
return "RESTARTING";
default:
throw new IllegalStateException();
}
}
/** Returns the failure string for the given failure reason value. */
public static String getFailureString(@FailureReason int failureReason) {
switch (failureReason) {
case FAILURE_REASON_NONE:
return "NO_REASON";
case FAILURE_REASON_UNKNOWN:
return "UNKNOWN_REASON";
default:
throw new IllegalStateException();
}
}
/** The unique content id. */
public final String id;
/** The type of the content. */
public final String type;
/** The Uri of the content. */
public final Uri uri;
/** A custom key for cache indexing. */
@Nullable public final String cacheKey;
/** The state of the download. */
@State public final int state;
/** The estimated download percentage, or {@link C#PERCENTAGE_UNSET} if unavailable. */
public final float downloadPercentage;
/** The total number of downloaded bytes. */
public final long downloadedBytes;
/** The total size of the media, or {@link C#LENGTH_UNSET} if unknown. */
public final long totalBytes;
/** The first time when download entry is created. */
public final long startTimeMs;
/** The last update time. */
public final long updateTimeMs;
/** Keys of streams to be downloaded. If empty, all streams will be downloaded. */
public final StreamKey[] streamKeys;
/** Optional custom data. */
public final byte[] customMetadata;
/**
* If {@link #state} is {@link #STATE_FAILED} then this is the cause, otherwise {@link
* #FAILURE_REASON_NONE}.
*/
@FailureReason public final int failureReason;
/** Download stop flags. These flags stop downloading any content. */
public final int stopFlags;
/* package */ DownloadState(
String id,
String type,
Uri uri,
@Nullable String cacheKey,
@State int state,
float downloadPercentage,
long downloadedBytes,
long totalBytes,
@FailureReason int failureReason,
@StopFlags int stopFlags,
long startTimeMs,
long updateTimeMs,
StreamKey[] streamKeys,
byte[] customMetadata) {
this.stopFlags = stopFlags;
Assertions.checkState(
failureReason == FAILURE_REASON_NONE ? state != STATE_FAILED : state == STATE_FAILED);
// TODO enable this when we start changing state immediately
// Assertions.checkState(stopFlags == 0 || (state != STATE_DOWNLOADING && state !=
// STATE_QUEUED));
this.id = id;
this.type = type;
this.uri = uri;
this.cacheKey = cacheKey;
this.streamKeys = streamKeys;
this.customMetadata = customMetadata;
this.state = state;
this.downloadPercentage = downloadPercentage;
this.downloadedBytes = downloadedBytes;
this.totalBytes = totalBytes;
this.failureReason = failureReason;
this.startTimeMs = startTimeMs;
this.updateTimeMs = updateTimeMs;
}
}
...@@ -20,8 +20,7 @@ import static org.junit.Assert.fail; ...@@ -20,8 +20,7 @@ import static org.junit.Assert.fail;
import android.net.Uri; import android.net.Uri;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState; import com.google.android.exoplayer2.offline.DownloadState.State;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState.State;
import com.google.android.exoplayer2.testutil.DummyMainThread; import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.RobolectricUtil; import com.google.android.exoplayer2.testutil.RobolectricUtil;
import com.google.android.exoplayer2.testutil.TestDownloadManagerListener; import com.google.android.exoplayer2.testutil.TestDownloadManagerListener;
...@@ -31,6 +30,7 @@ import java.io.IOException; ...@@ -31,6 +30,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.After; import org.junit.After;
...@@ -140,7 +140,7 @@ public class DownloadManagerTest { ...@@ -140,7 +140,7 @@ public class DownloadManagerTest {
public void postDownloadAction_downloads() throws Throwable { public void postDownloadAction_downloads() throws Throwable {
DownloadRunner runner = new DownloadRunner(uri1); DownloadRunner runner = new DownloadRunner(uri1);
TaskWrapper task = runner.postDownloadAction().getTask(); TaskWrapper task = runner.postDownloadAction().getTask();
task.assertStarted(); task.assertDownloading();
runner.getDownloader(0).unblock().assertReleased().assertStartCount(1); runner.getDownloader(0).unblock().assertReleased().assertStartCount(1);
task.assertCompleted(); task.assertCompleted();
runner.assertCreatedDownloaderCount(1); runner.assertCreatedDownloaderCount(1);
...@@ -151,9 +151,9 @@ public class DownloadManagerTest { ...@@ -151,9 +151,9 @@ public class DownloadManagerTest {
public void postRemoveAction_removes() throws Throwable { public void postRemoveAction_removes() throws Throwable {
DownloadRunner runner = new DownloadRunner(uri1); DownloadRunner runner = new DownloadRunner(uri1);
TaskWrapper task = runner.postRemoveAction().getTask(); TaskWrapper task = runner.postRemoveAction().getTask();
task.assertStarted(); task.assertRemoving();
runner.getDownloader(0).unblock().assertReleased().assertStartCount(1); runner.getDownloader(0).unblock().assertReleased().assertStartCount(1);
task.assertCompleted(); task.assertRemoved();
runner.assertCreatedDownloaderCount(1); runner.assertCreatedDownloaderCount(1);
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError(); downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
} }
...@@ -245,7 +245,7 @@ public class DownloadManagerTest { ...@@ -245,7 +245,7 @@ public class DownloadManagerTest {
runner.postRemoveAction(); runner.postRemoveAction();
downloader1.unblock().assertNotCanceled(); downloader1.unblock().assertNotCanceled();
runner.getTask().assertCompleted(); runner.getTask().assertRemoved();
runner.assertCreatedDownloaderCount(1); runner.assertCreatedDownloaderCount(1);
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError(); downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
} }
...@@ -341,7 +341,7 @@ public class DownloadManagerTest { ...@@ -341,7 +341,7 @@ public class DownloadManagerTest {
downloader2.unblock(); downloader2.unblock();
runner1.getTask().assertCompleted(); runner1.getTask().assertCompleted();
runner2.getTask().assertCompleted(); runner2.getTask().assertRemoved();
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError(); downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
} }
...@@ -387,8 +387,8 @@ public class DownloadManagerTest { ...@@ -387,8 +387,8 @@ public class DownloadManagerTest {
DownloadRunner runner2 = new DownloadRunner(uri2); DownloadRunner runner2 = new DownloadRunner(uri2);
DownloadRunner runner3 = new DownloadRunner(uri3); DownloadRunner runner3 = new DownloadRunner(uri3);
runner1.postDownloadAction().getTask().assertStarted(); runner1.postDownloadAction().getTask().assertDownloading();
runner2.postRemoveAction().getTask().assertStarted(); runner2.postRemoveAction().getTask().assertRemoving();
runner2.postDownloadAction(); runner2.postDownloadAction();
runOnMainThread(() -> downloadManager.stopDownloads()); runOnMainThread(() -> downloadManager.stopDownloads());
...@@ -404,7 +404,7 @@ public class DownloadManagerTest { ...@@ -404,7 +404,7 @@ public class DownloadManagerTest {
// When a new remove action is added, it cancels stopped download actions with the same media. // When a new remove action is added, it cancels stopped download actions with the same media.
runner1.postRemoveAction(); runner1.postRemoveAction();
runner1.getDownloader(1).assertStarted().unblock(); runner1.getDownloader(1).assertStarted().unblock();
runner1.getTask().assertCompleted(); runner1.getTask().assertRemoved();
// New download actions can be added but they don't start. // New download actions can be added but they don't start.
runner3.postDownloadAction().getDownloader(0).assertDoesNotStart(); runner3.postDownloadAction().getDownloader(0).assertDoesNotStart();
...@@ -521,14 +521,22 @@ public class DownloadManagerTest { ...@@ -521,14 +521,22 @@ public class DownloadManagerTest {
this.taskId = taskId; this.taskId = taskId;
} }
private TaskWrapper assertStarted() throws InterruptedException { private TaskWrapper assertDownloading() {
return assertState(DownloadState.STATE_STARTED); return assertState(DownloadState.STATE_DOWNLOADING);
} }
private TaskWrapper assertCompleted() { private TaskWrapper assertCompleted() {
return assertState(DownloadState.STATE_COMPLETED); return assertState(DownloadState.STATE_COMPLETED);
} }
private TaskWrapper assertRemoving() {
return assertState(DownloadState.STATE_REMOVING);
}
private TaskWrapper assertRemoved() {
return assertState(DownloadState.STATE_REMOVED);
}
private TaskWrapper assertFailed() { private TaskWrapper assertFailed() {
return assertState(DownloadState.STATE_FAILED); return assertState(DownloadState.STATE_FAILED);
} }
...@@ -542,6 +550,7 @@ public class DownloadManagerTest { ...@@ -542,6 +550,7 @@ public class DownloadManagerTest {
} }
private TaskWrapper assertState(@State int expectedState) { private TaskWrapper assertState(@State int expectedState) {
ArrayList<Integer> receivedStates = new ArrayList<>();
while (true) { while (true) {
Integer state = null; Integer state = null;
try { try {
...@@ -549,9 +558,25 @@ public class DownloadManagerTest { ...@@ -549,9 +558,25 @@ public class DownloadManagerTest {
} catch (InterruptedException e) { } catch (InterruptedException e) {
fail(e.getMessage()); fail(e.getMessage());
} }
assertThat(state).isNotNull(); if (state != null) {
if (expectedState == state) { if (expectedState == state) {
return this; return this;
}
receivedStates.add(state);
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < receivedStates.size(); i++) {
if (i > 0) {
sb.append(',');
}
sb.append(DownloadState.getStateString(receivedStates.get(i)));
}
fail(
String.format(
Locale.US,
"expected:<%s> but was:<%s>",
DownloadState.getStateString(expectedState),
sb));
} }
} }
} }
......
...@@ -23,7 +23,7 @@ import android.support.annotation.Nullable; ...@@ -23,7 +23,7 @@ import android.support.annotation.Nullable;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState; import com.google.android.exoplayer2.offline.DownloadState;
/** Helper for creating download notifications. */ /** Helper for creating download notifications. */
public final class DownloadNotificationUtil { public final class DownloadNotificationUtil {
...@@ -58,12 +58,14 @@ public final class DownloadNotificationUtil { ...@@ -58,12 +58,14 @@ public final class DownloadNotificationUtil {
boolean haveDownloadTasks = false; boolean haveDownloadTasks = false;
boolean haveRemoveTasks = false; boolean haveRemoveTasks = false;
for (DownloadState downloadState : downloadStates) { for (DownloadState downloadState : downloadStates) {
if (downloadState.state != DownloadState.STATE_STARTED if (downloadState.state == DownloadState.STATE_REMOVING
&& downloadState.state != DownloadState.STATE_COMPLETED) { || downloadState.state == DownloadState.STATE_RESTARTING
|| downloadState.state == DownloadState.STATE_REMOVED) {
haveRemoveTasks = true;
continue; continue;
} }
if (downloadState.action.isRemoveAction) { if (downloadState.state != DownloadState.STATE_DOWNLOADING
haveRemoveTasks = true; && downloadState.state != DownloadState.STATE_COMPLETED) {
continue; continue;
} }
haveDownloadTasks = true; haveDownloadTasks = true;
......
...@@ -19,7 +19,7 @@ import static com.google.common.truth.Truth.assertThat; ...@@ -19,7 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.os.ConditionVariable; import android.os.ConditionVariable;
import com.google.android.exoplayer2.offline.DownloadManager; import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadManager.DownloadState; import com.google.android.exoplayer2.offline.DownloadState;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment